Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
6 7u83 1
/*
2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
32
    		 Crown Copyright (c) 1997
33
 
34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
42
 
43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
45
 
46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
49
 
50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
53
 
54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
/* 80x86/cproc.c */
62
 
63
/**********************************************************************
64
$Author: release $
65
$Date: 1998/03/16 11:25:21 $
66
$Revision: 1.4 $
67
$Log: cproc.c,v $
68
 * Revision 1.4  1998/03/16  11:25:21  release
69
 * Modifications prior to version 4.1.2.
70
 *
71
 * Revision 1.3  1998/03/15  16:00:14  pwe
72
 * regtrack dwarf dagnostics added
73
 *
74
 * Revision 1.2  1998/03/11  11:03:03  pwe
75
 * DWARF optimisation info
76
 *
77
 * Revision 1.1.1.1  1998/01/17  15:55:51  release
78
 * First version to be checked into rolling release.
79
 *
80
 * Revision 1.31  1997/10/23  09:36:56  pwe
81
 * extra_diags
82
 *
83
 * Revision 1.30  1997/10/10  18:25:03  pwe
84
 * prep ANDF-DE revision
85
 *
86
 * Revision 1.29  1997/08/23  13:45:28  pwe
87
 * initial ANDF-DE
88
 *
89
 * Revision 1.28  1997/05/02  11:04:47  pwe
90
 * minor dwarf2 corrections
91
 *
92
 * Revision 1.27  1997/04/17  11:55:43  pwe
93
 * dwarf2 improvements
94
 *
95
 * Revision 1.26  1997/04/02  10:33:10  pwe
96
 * diagnose pl_tests
97
 *
98
 * Revision 1.25  1997/03/24  11:15:08  pwe
99
 * dwarf2 option/default
100
 *
101
 * Revision 1.24  1997/03/20  16:23:35  pwe
102
 * dwarf2
103
 *
104
 * Revision 1.23  1996/12/13  14:39:19  pwe
105
 * prep NEWDIAGS
106
 *
107
 * Revision 1.22  1996/11/08  16:19:02  pwe
108
 * check_stack to check before modifying stack
109
 *
110
 * Revision 1.21  1996/10/31  12:02:33  pwe
111
 * correct env_offset used in constant evaluation
112
 *
113
 * Revision 1.20  1996/10/29  13:50:51  pwe
114
 * correct space for patched instructions
115
 *
116
 * Revision 1.19  1996/10/08  07:58:56  pwe
117
 * revised correction to env_offset v id out_of_line
118
 *
119
 * Revision 1.18  1996/10/07  13:31:06  pwe
120
 * push make_value, and env_offset v id out_of_line
121
 *
122
 * Revision 1.17  1996/07/31  12:56:53  pwe
123
 * restore alloca stack after longjump
124
 *
125
 * Revision 1.16  1996/07/09  09:43:35  pwe
126
 * caller env_offset if callees present, and tidy
127
 *
128
 * Revision 1.15  1996/02/08  13:45:12  pwe
129
 * Linux elf v aout option
130
 *
131
 * Revision 1.14  1996/01/10  09:19:03  pwe
132
 * profile const & envoffset correction
133
 *
134
 * Revision 1.13  1996/01/05  16:25:22  pwe
135
 * env_size and env_offset within constant expressions
136
 *
137
 * Revision 1.12  1995/12/22  09:34:27  pwe
138
 * solaris diags for stack objects
139
 *
140
 * Revision 1.11  1995/12/21  13:47:02  pwe
141
 * trap for missing pops (sco problem)
142
 *
143
 * Revision 1.10  1995/10/13  15:19:47  pwe
144
 * solaris PIC and linux tcc
145
 *
146
 * Revision 1.9  1995/10/09  15:14:09  pwe
147
 * dynamic initialisation etc
148
 *
149
 * Revision 1.8  1995/09/05  16:24:45  pwe
150
 * specials and exception changes
151
 *
152
 * Revision 1.7  1995/08/30  16:06:24  pwe
153
 * prepare exception trapping
154
 *
155
 * Revision 1.6  1995/08/23  09:42:39  pwe
156
 * track fpu control word for trap etc
157
 *
158
 * Revision 1.5  1995/08/14  13:53:30  pwe
159
 * several corrections, tail calls and error jumps
160
 *
161
 * Revision 1.4  1995/08/04  08:29:09  pwe
162
 * 4.0 general procs implemented
163
 *
164
 * Revision 1.3  1995/04/13  11:38:57  pwe
165
 * odd_bits clean for proc ending with bottom
166
 *
167
 * Revision 1.2  1995/01/30  12:56:04  pwe
168
 * Ownership -> PWE, tidy banners
169
 *
170
 * Revision 1.1  1994/10/27  14:15:22  jmf
171
 * Initial revision
172
 *
173
 * Revision 1.1  1994/07/12  14:29:47  jmf
174
 * Initial revision
175
 *
176
**********************************************************************/
177
 
178
 
179
/**********************************************************************
180
   cproc produces the code for the procedure defined by which has
181
   name pname.
182
 
183
**********************************************************************/
184
 
185
#include "config.h"
186
#include "common_types.h"
187
#include "weights.h"
188
#include "basicread.h"
189
#include "tags.h"
190
#include "codermacs.h"
191
#include "instr386.h"
192
#include "expmacs.h"
193
#include "exp.h"
194
#include "operand.h"
195
#include "shapemacs.h"
196
#include "instr.h"
197
#include "instrmacs.h"
198
#include "out.h"
199
#include "check.h"
200
#include "flags.h"
201
#include "codec.h"
202
#include "xalloc.h"
203
#include "global_opt.h"
204
#include "reg_record.h"
205
#include "externs.h"
206
#include "install_fns.h"
207
#include "installglob.h"
208
#include "machine.h"
209
#include "localflags.h"
210
#include "diag_fns.h"
211
#include "messages_8.h"
212
#include "assembler.h"
213
#include "coder.h"
214
#include "scan2.h"
215
#include "cproc.h"
216
 
217
#ifdef NEWDWARF
218
#include "dw2_config.h"
219
#include "dw2_info.h"
220
#include "dw2_basic.h"
221
#include "dw2_extra.h"
222
#endif
223
 
224
static exp returns_list;
225
 
226
int locals_offset;	/* global, needed for solaris stabs */
227
exp hasenvoff_list = nilexp;	/* global, used by coder */
228
 
229
/* MACROS */
230
 
231
#define GLOBALTABLEMASK 0x8
232
 
233
/* PROCEDURES */
234
 
235
static void
236
add_odd_bits(outofline * r)
237
{
238
  if (r != (outofline*)0) {
239
    if (r -> next == (outofline*)0)
240
      last_odd_bit = 1;
241
    add_odd_bits(r -> next);
242
  }
243
  else
244
    return;
245
 
246
  current_odd_bit = r;
247
  if (is80486)
248
    dot_align(4);
249
  simple_set_label(r->labno);
250
  clear_reg_record(crt_reg_record);
251
#ifdef NEWDWARF
252
  if (dwarf2) {
253
#if 1
254
    dw2_start_extra_bit(r->body);
255
#else
256
    dw2_start_extra_bit(r->dw2_slave);
257
#endif
258
    START_BB();
259
  }
260
#endif
261
 
262
  regsinuse = r->regsinuse;
263
  fstack_pos = r->fstack_pos;
264
  cond1_set = r->cond1_set;
265
  cond2_set = r->cond2_set;
266
  cond1 = r->cond1;
267
  cond2a = r->cond2a;
268
  cond2b = r->cond2b;
269
  repeat_level = r->repeat_level;
270
  scale = r->scale;
271
  coder(r->dest, r->stack, r->body);
272
  if (name(sh(r->body))!= bothd) {
273
    clean_stack();
274
    jump(r->jr, 0);
275
  }
276
  else
277
    stack_dec = 0;
278
#ifdef NEWDWARF
279
  if (dwarf2)
280
#if 1
281
    dw2_end_extra_bit(r->body);
282
#else
283
    dw2_end_extra_bit(r->dw2_hi);
284
#endif
285
#endif
286
  return;
287
}
288
 
289
static void
290
out_pops(int tot_sp, int push_space, int extra, int dpos)
291
{
292
#ifdef NEWDWARF
293
  int st;
294
  long dwl0 = 0, dwl1 = 0, dwl2 = 0, dwl3 = 0, dwl4 = 0;
295
#endif
296
  tot_sp -= extra;
297
  if (no_frame && !stack_aligned_8byte) {
298
    if (tot_sp != push_space) {
299
      outs(" addl $");
300
      outn((long)(tot_sp - push_space));
301
      outs(",%esp");
302
      outnl();
303
#ifdef NEWDWARF
304
      if (diagnose && dwarf2)
305
	dwl0 = set_dw_text_label();
306
#endif
307
    };
308
  }
309
  else {
310
    if (tot_sp != push_space || has_alloca || stack_aligned_8byte) {
311
      outs(" leal -");
312
      outn((long)push_space);
313
      outs("(%ebp),%esp");
314
      outnl();
315
    };
316
  };
317
 
318
  /* pop the registers at the end */
319
  if (no_frame && (min_rfree & 0x40)) {
320
    outs(" pop %ebp");
321
    outnl();
322
#ifdef NEWDWARF
323
    if (diagnose && dwarf2)
324
      dwl1 = set_dw_text_label();
325
#endif
326
  };
327
  if (min_rfree & 0x20) {
328
    outs(" pop %esi");
329
    outnl();
330
#ifdef NEWDWARF
331
    if (diagnose && dwarf2)
332
      dwl2 = set_dw_text_label();
333
#endif
334
  };
335
  if (min_rfree & 0x10) {
336
    outs(" pop %edi");
337
    outnl();
338
#ifdef NEWDWARF
339
    if (diagnose && dwarf2)
340
      dwl3 = set_dw_text_label();
341
#endif
342
  };
343
  if (min_rfree & 0x8) {
344
    outs(" pop %ebx");
345
    outnl();
346
#ifdef NEWDWARF
347
    if (diagnose && dwarf2)
348
      dwl4 = set_dw_text_label();
349
#endif
350
  };
351
 
352
  if (!no_frame) {
353
    outs(" pop %ebp");
354
    outnl();
355
#ifdef NEWDWARF
356
    if (diagnose && dwarf2)
357
      dwl1 = set_dw_text_label();
358
#endif
359
  };
360
  outnl();
361
#ifdef NEWDWARF
362
  if (diagnose && dwarf2) {
363
    st = fseek(fpout, dpos, 0);
364
    if (st == -1) {
365
      failer(SEEK_FAILURE);
366
      exit(EXIT_FAILURE);
367
    };
368
    dw2_fde_restore_args(dwl0, dwl1, dwl2, dwl3, dwl4, push_space);
369
  }
370
#endif
371
  return;
372
}
373
 
374
static void
375
out_untidy_pops(int tot_sp, int push_space)
376
{
377
  if (no_frame) {
378
    int s_offset = tot_sp - push_space;
379
    if (min_rfree & 0x40) {
380
      outs(" movl ");
381
      outn((long)s_offset);
382
      outs("(%esp),%ebp");
383
      outnl();
384
      s_offset += 4;
385
    };
386
    if (min_rfree & 0x20) {
387
      outs(" movl ");
388
      outn((long)s_offset);
389
      outs("(%esp),%esi");
390
      outnl();
391
      s_offset += 4;
392
    };
393
    if (min_rfree & 0x10) {
394
      outs(" movl ");
395
      outn((long)s_offset);
396
      outs("(%esp),%edi");
397
      outnl();
398
      s_offset += 4;
399
    };
400
    if (min_rfree & 0x8) {
401
      outs(" movl ");
402
      outn((long)s_offset);
403
      outs("(%esp),%ebx");
404
      outnl();
405
      /* s_offset += 4; */
406
    };
407
  }
408
  else {
409
    int fm_offset = - push_space;
410
    if (min_rfree & 0x20) {
411
      outs(" movl ");
412
      outn((long)fm_offset);
413
      outs("(%ebp),%esi");
414
      outnl();
415
      fm_offset += 4;
416
    };
417
    if (min_rfree & 0x10) {
418
      outs(" movl ");
419
      outn((long)fm_offset);
420
      outs("(%ebp),%edi");
421
      outnl();
422
      fm_offset += 4;
423
    };
424
    if (min_rfree & 0x8) {
425
      outs(" movl ");
426
      outn((long)fm_offset);
427
      outs("(%ebp),%ebx");
428
      outnl();
429
      /* fm_offset += 4; */
430
    };
431
    outs(" movl 0(%ebp),%ebp");
432
    outnl();
433
  };
434
  return;
435
}
436
 
437
 
438
int
439
cproc(exp p, char *pname, int cname, int global, diag_global *diag_props)
440
{
441
  exp jr, t, body;
442
  ash stack;
443
  int  ms;
444
  int tot_sp;
445
  int param_pos;
446
  int byte_stack_align = stack_align / 8;
447
  int   st;
448
  long  old_pos1,
449
        old_pos1a,
450
        old_pos2,
451
        old_pos3,
452
        old_pos4,
453
        old_pos5,
454
        old_pos8,
455
        old_pos9,
456
        this_pos;
457
  int  push_space = 0;
458
#ifdef NEWDWARF
459
  long dwl0, dwl8, dw_entry_pos;
460
  long dwl1 = 0, dwl2 = 0, dwl3 = 0, dwl4 = 0;
461
  char * dw_labroom = "                 ";
462
		     /* .Ldw12345678:\n */
463
#endif
464
 
465
  int request_align_8byte;
466
 
467
  returns_list = nilexp;
468
  crt_proc_exp = p;
469
  crt_proc_id = next_lab();
470
  crt_ret_lab = next_lab ();	/* set up the return label for the
471
				   procedure */
472
  crt_ret_lab_used = 0;
473
  odd_bits = (outofline*)0;
474
  scale = (float)1.0;
475
  not_in_params = 1;
476
  not_in_postlude = 1;
477
  keep_short = 0;
478
  repeat_level = 0;
479
  callee_size = (proc_has_vcallees(p)? -1 : 0);
480
  ferrsize = 0;
481
  fpucon = normal_fpucon;
482
 
483
  has_dy_callees = 0;		/* set by scan2 when stack_dec indeterminable */
484
  has_tail_call = 0;		/* set by scan2, used in coder */
485
  has_same_callees = 0;		/* set by scan2, used in coder */
486
  proc_has_asm = 0;		/* set by scan2 if any asm operands */
487
  IGNORE scan2(1, p, p, 0);
488
  useful_double = 0;
489
  comp_weights(p);
490
 
491
/* 8byte align */
492
  request_align_8byte = permit_8byte_align && useful_double;
493
 
494
  if (pname[0]!= local_prefix[0])
495
    proc_type(pname);
496
 
497
  has_alloca = proc_has_alloca(p);
498
 
499
  must_use_bp = (has_alloca || proc_has_lv(p));
500
 
501
  regsinuse = 0;
502
 
503
  no_frame = 1;
504
  if (always_use_frame || do_profile || must_use_bp || has_dy_callees ||
505
        proc_uses_crt_env(p) || proc_has_setjmp(p) || proc_has_asm
506
    )
507
     no_frame = 0;
508
 
509
  if (request_align_8byte && no_frame) {
510
    no_frame = 0;
511
    stack_aligned_8byte = 1;
512
  }
513
  else
514
    stack_aligned_8byte = 0;
515
 
516
  if (!no_frame)
517
    regsinuse = 0x40; /* prevent ebp from being used as an ordinary
518
                          register */
519
 
520
  fstack_pos = first_fl_reg;
521
 
522
  max_stack = 0;		/* maximum stack value attained */
523
  max_extra_stack = 0;		/* maximum stack value attained */
524
  min_rfree = 0;		/* total registers used */
525
  stack_dec = 0;		/* current stack decrement */
526
  cond1_set = 0;
527
  cond2_set = 0;		/* state of condition flags is not known
528
				*/
529
  clear_reg_record(crt_reg_record);
530
  stack.ashsize = 0;
531
  stack.ashalign = 0;
532
 
533
 
534
 
535
  vc_pointer = nilexp;
536
				/* set up params before any diagnostics */
537
  t = son(p);
538
  param_pos = 0;
539
  while (name(t) == ident_tag && isparam(t) && name(son(t))!= formal_callee_tag)
540
   {
541
     t = bro(son(t));
542
   };
543
  if (name(t) == ident_tag && name(son(t)) == formal_callee_tag)
544
   {
545
     if (callee_size < 0)
546
	vc_pointer = t;
547
     while (name(t) == ident_tag && name(son(t)) == formal_callee_tag)
548
      {
549
	ptno(t) = par_pl;
550
	no(t) = param_pos;
551
	if (isenvoff(t))
552
	  set_env_off(param_pos+64, t);
553
	param_pos = rounder(param_pos + shape_size(sh(son(t))), param_align);
554
	t = bro(son(t));
555
      };
556
     if (callee_size == 0)
557
	callee_size = param_pos;
558
   };
559
   {
560
     exp pp = son(p);
561
     while (name(pp) == ident_tag && isparam(pp) && name(son(pp))!= formal_callee_tag)
562
      {
563
	ptno(pp) = par_pl;
564
	no(pp) = param_pos;
565
	if (isenvoff(pp))
566
	  set_env_off(param_pos+64, pp);
567
	param_pos = rounder(param_pos + shape_size(sh(son(pp))), param_align);
568
	pp = bro(son(pp));
569
      };
570
   };
571
 
572
  body = t;
573
 
574
 
575
 
576
 
577
  if (global) {
578
    outs(".globl ");
579
    outs(pname);
580
    outnl();
581
  };
582
 
583
  if (is80486)
584
    dot_align(16);
585
  else
586
    dot_align(4);
587
 
588
  if (diagnose)
589
#ifdef NEWDWARF
590
    DIAG_PROC_BEGIN(diag_props, global, cname, pname, p);
591
#else
592
    diag_proc_begin(diag_props, global, cname, pname);
593
#endif
594
 
595
  if (cname == -1)
596
    outs(pname);
597
  else
598
    {
599
      outs(local_prefix);
600
      outn((long)cname);
601
    };
602
  outs(":");
603
  outnl();
604
#ifdef NEWDWARF
605
  if (diagnose && dwarf2) {
606
    START_BB();
607
    dwl0 = set_dw_text_label();
608
  }
609
#endif
610
 
611
/* space for setting local displacement label */
612
  if (flush_before_tell)
613
    IGNORE fflush(fpout);
614
  old_pos1 = ftell(fpout);
615
  outs("                          ");
616
     /* ".set .LdispNNNN, SSSSS\n" */
617
  outnl();
618
  if (flush_before_tell)
619
    IGNORE fflush(fpout);
620
  old_pos1a = ftell(fpout);
621
  outs("                             ");
622
     /* ".set .LfcwdispNNNN, SSSSS\n" */
623
  outnl();
624
 
625
  if (!no_frame) {
626
    outs(" pushl %ebp");
627
    outnl();
628
    outs(" movl %esp,%ebp");
629
    outnl();
630
#ifdef NEWDWARF
631
    if (diagnose && dwarf2)
632
      dwl1 = set_dw_text_label();
633
#endif
634
  };
635
 
636
/* space for pushing fixed point registers */
637
  if (flush_before_tell)
638
    IGNORE fflush(fpout);
639
  old_pos2 = ftell(fpout);
640
  outs("               ");
641
     /* " pushl %ebx\n" */
642
#ifdef NEWDWARF
643
  if (diagnose && dwarf2)
644
    outs(dw_labroom);
645
#endif
646
  outnl();
647
  if (flush_before_tell)
648
    IGNORE fflush(fpout);
649
  old_pos3 = ftell(fpout);
650
  outs("               ");
651
     /* " pushl %edi\n" */
652
#ifdef NEWDWARF
653
  if (diagnose && dwarf2)
654
    outs(dw_labroom);
655
#endif
656
  outnl();
657
  if (flush_before_tell)
658
    IGNORE fflush(fpout);
659
  old_pos4 = ftell(fpout);
660
  outs("               ");
661
     /* " pushl %esi\n" */
662
#ifdef NEWDWARF
663
  if (diagnose && dwarf2)
664
    outs(dw_labroom);
665
#endif
666
  outnl();
667
  if (no_frame) {
668
    if (flush_before_tell)
669
      IGNORE fflush(fpout);
670
    old_pos5 = ftell(fpout);
671
    outs("               ");
672
       /* " pushl %ebp\n" */
673
#ifdef NEWDWARF
674
    if (diagnose && dwarf2)
675
      outs(dw_labroom);
676
#endif
677
    outnl();
678
  }
679
 
680
/* space for subtract from stack pointer */
681
  if (flush_before_tell)
682
    IGNORE fflush(fpout);
683
  old_pos8 = ftell(fpout);
684
  outs("                     ");
685
     /* " subl $SSSSS,%esp\n" */
686
     /* " movl $SSSSS,%eax\n" */
687
  outnl();
688
  if (proc_has_checkstack(p)) {
689
    checkalloc_stack(reg0, 1);
690
  };
691
#ifdef NEWDWARF
692
  if (diagnose && dwarf2) {
693
    dwl8 = set_dw_text_label();
694
    dw_entry_pos = dw2_start_fde(dwl0, dwl1);
695
  }
696
#endif
697
 
698
  if (stack_aligned_8byte) {
699
    outs(" andl $-8,%esp");
700
    outnl();
701
  };
702
 
703
  if (flush_before_tell)
704
    IGNORE fflush(fpout);
705
  old_pos9 = ftell(fpout);
706
  outs("                                    ");
707
     /* "movw $DDDD,0-.LfcwdispNNNN(%ebp)\n" */
708
  outnl();
709
 
710
 
711
#if isdragonfly || isfreebsd || islinux
712
  if (
713
#if isdragonfly
714
  !dragonfly_elf &&
715
#elif isfreebsd
716
  !freebsd_elf &&
717
#elif islinux
718
	!linux_elf &&
719
#endif
720
	pname[0]!= local_prefix[0] &&
721
	!strcmp(pname+prefix_length, "main")) {
722
    out_main_prelude();
723
  }
724
#endif
725
 
726
  if (do_profile) {
727
    int  labl = next_lab ();	/* output profile procedure header */
728
    outs(".data");
729
    outnl();
730
    dot_align(4);
731
    outs(local_prefix);
732
    outs("P");
733
    outn((long)labl);
734
    outs(":");
735
    outnl();
736
    outs(" .long 0");
737
    outnl();
738
    outs(".text");
739
    outnl();
740
    outs(" leal ");
741
    outs(local_prefix);
742
    outs("P");
743
    outn((long)labl);
744
    outs(",%edx");
745
    outnl();
746
    outs(" call _mcount");
747
    outnl();
748
  };
749
 
750
 
751
  if (PIC_code && proc_uses_external(p))
752
   {
753
     regsinuse |= GLOBALTABLEMASK;
754
     min_rfree |= GLOBALTABLEMASK;
755
     pic_prelude();
756
   };
757
 
758
  need_preserve_stack = 0;
759
  if (proc_uses_crt_env(p) && proc_has_lv(p) && has_alloca)
760
   {
761
     need_preserve_stack = 1;
762
     stack.ashsize += 32;
763
     max_stack = stack.ashsize;
764
     save_stack();
765
   };
766
 
767
  scale = (float)1.0;
768
  last_odd_bit = 0;
769
  doing_odd_bits = 0;
770
  coder (zero, stack, body); /* code body of procedure */
771
 
772
  stack_dec = 0;
773
  doing_odd_bits = 1;
774
  while (odd_bits != (outofline*)0) {
775
    outofline * ol = odd_bits;
776
    odd_bits = (outofline*)0;
777
    last_odd_bit = 0;
778
    add_odd_bits(ol);
779
  }
780
 
781
 
782
  if (crt_ret_lab_used) {
783
    jr = getexp(f_bottom, nilexp, 0, nilexp, nilexp, 0,
784
                0, 0);
785
    sonno(jr) = stack_dec;
786
    ptno(jr) = crt_ret_lab;
787
    fstack_pos_of(jr) = (prop)first_fl_reg;
788
    set_label(jr);
789
  };
790
 
791
	/* If the procedure loads the current env and uses make_lv
792
	   it may be the destination of a long_jump. In that case
793
	   ebx, esi and edi must be saved at and restored at exit.
794
	   ebp will be saved and restored anyway because such a
795
	   procedure will have a frame pointer.
796
	*/
797
  if (proc_uses_crt_env(p) && proc_has_lv(p))
798
    min_rfree |= 0x38;
799
 
800
  /* compute space needed for local variables in memory */
801
  ms = ((max_stack + 31) / 32)* 4;
802
  /* compute space needed for pushing registers */
803
  if (no_frame && min_rfree & 0x40)
804
    push_space += 4;
805
  if (min_rfree & 0x20)
806
    push_space += 4;
807
  if (min_rfree & 0x10)
808
    push_space += 4;
809
  if (min_rfree & 0x8)
810
    push_space += 4;
811
 
812
  ferrsize /= 8;
813
  tot_sp = rounder(ms + push_space + ferrsize, byte_stack_align);
814
 
815
  if (crt_ret_lab_used) {
816
#ifdef NEWDWARF
817
    long over_lab;
818
    if (diagnose && dwarf2) {
819
      over_lab = next_dwarf_label();
820
      dw2_return_pos(over_lab);
821
    }
822
#endif
823
    restore_callregs(0);
824
    retins();
825
    outnl();
826
#ifdef NEWDWARF
827
    if (diagnose && dwarf2)
828
      dw2_after_fde_exit(over_lab);
829
#endif
830
  };
831
  outnl();
832
 
833
  this_pos = ftell(fpout);
834
  while (returns_list != nilexp) {
835
    st = fseek(fpout,(long)no(returns_list), 0);
836
    if (st == -1) {
837
      failer(SEEK_FAILURE);
838
      exit(EXIT_FAILURE);
839
    };
840
    if (name(returns_list) == 1)
841
      out_untidy_pops(tot_sp, push_space);
842
    else
843
      out_pops(tot_sp, push_space, ptno(returns_list) /8, sonno(returns_list));
844
    returns_list = bro(returns_list);
845
  };
846
  fseek(fpout, this_pos, 0);
847
 
848
  locals_offset = tot_sp;
849
  if (diagnose) {
850
    no (p) = tot_sp;	/* may be used by delayed diagnostics */
851
#ifdef NEWDWARF
852
    DIAG_PROC_END(diag_props, p);
853
#else
854
    diag_proc_end(diag_props);
855
#endif
856
#ifdef NEWDWARF
857
  if (dwarf2)
858
    dw2_complete_fde();
859
#endif
860
  }
861
 
862
  /* now set in the information at the head of the procedure */
863
  {
864
 
865
    if (flush_before_tell)
866
      IGNORE fflush(fpout);
867
    this_pos = ftell(fpout);
868
    st = fseek(fpout, old_pos1, 0);
869
    if (st == -1) {
870
      failer(SEEK_FAILURE);
871
      exit(EXIT_FAILURE);
872
    };
873
 
874
    /* set the label which says how much the stack was decreased, in case
875
       frame pointer addressing is used  */
876
    outs(".set ");
877
    outs(local_prefix);
878
    outs("disp");
879
    outn((long)crt_proc_id);
880
    outs(", ");
881
    outn((long)tot_sp);
882
 
883
    if (ferrsize != 0) {
884
	/* set label for displacement to fpu control local store */
885
      st = fseek(fpout, old_pos1a, 0);
886
      if (st == -1) {
887
        failer(SEEK_FAILURE);
888
        exit(EXIT_FAILURE);
889
      };
890
      outs(".set ");
891
      outs(local_prefix);
892
      outs("fcwdisp");
893
      outn((long)crt_proc_id);
894
      outs(", ");
895
      outn((long)((no_frame)?(tot_sp - push_space - ferrsize):(push_space + ferrsize)));
896
    }
897
 
898
    st = fseek(fpout, this_pos, 0);
899
    if (st == -1) {
900
      failer(SEEK_FAILURE);
901
      exit(EXIT_FAILURE);
902
    };
903
  };
904
 
905
  if (tot_sp != push_space || proc_has_checkstack(p)) {
906
    if (flush_before_tell)
907
      IGNORE fflush(fpout);
908
    this_pos = ftell(fpout);
909
    st = fseek(fpout, old_pos8, 0);
910
    if (st == -1) {
911
      failer(SEEK_FAILURE);
912
      exit(EXIT_FAILURE);
913
    };
914
 
915
    /* decrease the stack if necessary */
916
    if (proc_has_checkstack(p)) {
917
      outs(" movl $");
918
      outn((long)(tot_sp - push_space));
919
      outs(",%eax");
920
    }
921
    else {
922
      outs(" subl $");
923
      outn((long)(tot_sp - push_space));
924
      outs(",%esp");
925
    };
926
    outnl();
927
 
928
    if (ferrsize != 0) {	/* record FPU control word */
929
      st = fseek(fpout, old_pos9, 0);
930
      if (st == -1) {
931
        failer(SEEK_FAILURE);
932
        exit(EXIT_FAILURE);
933
      };
934
      move(uwordsh, mw(zeroe, normal_fpucon), mw(ferrmem, 0));
935
    }
936
 
937
    st = fseek(fpout, this_pos, 0);
938
    if (st == -1) {
939
      failer(SEEK_FAILURE);
940
      exit(EXIT_FAILURE);
941
    };
942
  };
943
 
944
  /* push registers as necessary */
945
  if (min_rfree & 0x8) {
946
    st = fseek(fpout, old_pos2, 0);
947
    if (st == -1) {
948
      failer(SEEK_FAILURE);
949
      exit(EXIT_FAILURE);
950
    };
951
    outs(" pushl %ebx");
952
    outnl();
953
#ifdef NEWDWARF
954
    if (diagnose && dwarf2)
955
      dwl2 = set_dw_text_label();
956
#endif
957
  };
958
 
959
  if (min_rfree & 0x10) {
960
    st = fseek(fpout, old_pos3, 0);
961
    if (st == -1) {
962
      failer(SEEK_FAILURE);
963
      exit(EXIT_FAILURE);
964
    };
965
    outs(" pushl %edi");
966
    outnl();
967
#ifdef NEWDWARF
968
    if (diagnose && dwarf2)
969
      dwl3 = set_dw_text_label();
970
#endif
971
  };
972
 
973
 
974
  if (min_rfree & 0x20) {
975
    st = fseek(fpout, old_pos4, 0);
976
    if (st == -1) {
977
      failer(SEEK_FAILURE);
978
      exit(EXIT_FAILURE);
979
    };
980
    outs(" pushl %esi");
981
    outnl();
982
#ifdef NEWDWARF
983
    if (diagnose && dwarf2)
984
      dwl4 = set_dw_text_label();
985
#endif
986
  };
987
 
988
  if (no_frame && (min_rfree & 0x40)) {
989
    st = fseek(fpout, old_pos5, 0);
990
    if (st == -1) {
991
      failer(SEEK_FAILURE);
992
      exit(EXIT_FAILURE);
993
    };
994
    outs(" pushl %ebp");
995
    outnl();
996
#ifdef NEWDWARF
997
    if (diagnose && dwarf2)
998
      dwl1 = set_dw_text_label();
999
#endif
1000
  };
1001
 
1002
#ifdef NEWDWARF
1003
  if (diagnose && dwarf2) {
1004
    st = fseek(fpout, dw_entry_pos, 0);
1005
    if (st == -1) {
1006
      failer(SEEK_FAILURE);
1007
      exit(EXIT_FAILURE);
1008
    };
1009
    dw2_fde_entry(dwl0, dwl1, dwl2, dwl3, dwl4, dwl8, tot_sp);
1010
  };
1011
#endif
1012
 
1013
  st = fseek(fpout, this_pos, 0);
1014
  if (st == -1) {
1015
    failer(SEEK_FAILURE);
1016
    exit(EXIT_FAILURE);
1017
  };
1018
 
1019
  if (pname[0]!= local_prefix[0])
1020
    proc_size(pname);
1021
 
1022
  if (proc_needs_envsize(p)) {
1023
    outs(".set ");
1024
    outs(local_prefix);
1025
    outs("ESZ");
1026
    outs(pname);
1027
    outs(", ");
1028
    outn((long)(tot_sp + 4 + max_extra_stack/8));
1029
    outnl();
1030
  }
1031
 
1032
#if isdragonfly || isfreebsd || islinux
1033
  if (
1034
#if isdragonfly
1035
  !dragonfly_elf &&
1036
#elif isfreebsd
1037
  !freebsd_elf &&
1038
#elif islinux
1039
	!linux_elf &&
1040
#endif
1041
	pname[0]!= local_prefix[0] &&
1042
	!strcmp(pname+prefix_length, "main")) {
1043
    out_main_postlude();
1044
  }
1045
#endif
1046
 
1047
  /* now prepare params with env_offset for possible constant evaluation */
1048
  t = son(p);
1049
  while (name(t) == ident_tag && isparam(t)) {
1050
    if (isenvoff(t)) {
1051
      no(t) += 64;
1052
      name(t) = 0;
1053
      ptno(t) = local_pl;
1054
    }
1055
    t = bro(son(t));
1056
  }
1057
  while (hasenvoff_list != nilexp) {
1058
    exp id = son(hasenvoff_list);
1059
    exp next = bro(hasenvoff_list);
1060
    no(id) -= (locals_offset * 8);
1061
    name(id) = 0;
1062
    retcell(hasenvoff_list);
1063
    hasenvoff_list = next;
1064
  }
1065
 
1066
  if (no_frame)			/* hold info for later diagnostics */
1067
    clear_proc_has_fp(p);
1068
  else
1069
    set_proc_has_fp(p);
1070
 
1071
  return(proc_needs_envsize(p)? tot_sp + 4 + max_extra_stack/8 : 0);
1072
}
1073
 
1074
 
1075
/* Restore call_save registers (%ebp, %esi, %edi, %ebx)
1076
   when we know which ones are reused.
1077
   This preserves %eax, %ecx, %edx */
1078
void restore_callregs
1079
(int untidy)
1080
{
1081
  char *sp50 = "                                                  ";
1082
  long retpos = ftell(fpout);
1083
  outs("?");	/* will be overwritten, to cause assembler fail if sco bug */
1084
  outs(sp50); outs(sp50); outs(sp50);
1085
  outnl();
1086
  returns_list = getexp(f_top, returns_list, 0, nilexp,
1087
				nilexp, 0, 0,(unsigned char)untidy);
1088
  no(returns_list) = (int)retpos;
1089
  ptno(returns_list) = stack_dec;
1090
#ifdef NEWDWARF
1091
  if (diagnose && dwarf2)
1092
    sonno(returns_list) = (int)dw2_prep_fde_restore_args(untidy);
1093
#endif
1094
  return;
1095
}