aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
blob: 529c5bfe22b8c3f38d00590c182588cf6980cc98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
/* Convert function calls to rtl insns, for GNU C compiler.
   Copyright (C) 1989, 1992 Free Software Foundation, Inc.

This file is part of GNU CC.

GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

#include "config.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
#include "expr.h"
#include "insn-flags.h"

/* Decide whether a function's arguments should be processed
   from first to last or from last to first.  */

#ifdef STACK_GROWS_DOWNWARD
#ifdef PUSH_ROUNDING
#define PUSH_ARGS_REVERSED	/* If it's last to first */
#endif
#endif

/* Like STACK_BOUNDARY but in units of bytes, not bits.  */
#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)

/* Data structure and subroutines used within expand_call.  */

struct arg_data
{
  /* Tree node for this argument.  */
  tree tree_value;
  /* Current RTL value for argument, or 0 if it isn't precomputed.  */
  rtx value;
  /* Initially-compute RTL value for argument; only for const functions.  */
  rtx initial_value;
  /* Register to pass this argument in, 0 if passed on stack, or an
     EXPR_LIST if the arg is to be copied into multiple different
     registers.  */
  rtx reg;
  /* Number of registers to use.  0 means put the whole arg in registers.
     Also 0 if not passed in registers.  */
  int partial;
  /* Non-zero if argument must be passed on stack.  */
  int pass_on_stack;
  /* Offset of this argument from beginning of stack-args.  */
  struct args_size offset;
  /* Similar, but offset to the start of the stack slot.  Different from
     OFFSET if this arg pads downward.  */
  struct args_size slot_offset;
  /* Size of this argument on the stack, rounded up for any padding it gets,
     parts of the argument passed in registers do not count.
     If REG_PARM_STACK_SPACE is defined, then register parms
     are counted here as well.  */
  struct args_size size;
  /* Location on the stack at which parameter should be stored.  The store
     has already been done if STACK == VALUE.  */
  rtx stack;
  /* Location on the stack of the start of this argument slot.  This can
     differ from STACK if this arg pads downward.  This location is known
     to be aligned to FUNCTION_ARG_BOUNDARY.  */
  rtx stack_slot;
#ifdef ACCUMULATE_OUTGOING_ARGS
  /* Place that this stack area has been saved, if needed.  */
  rtx save_area;
#endif
};

#ifdef ACCUMULATE_OUTGOING_ARGS
/* A vector of one char per word of stack space.  A byte if non-zero if
   the corresponding stack location has been used.
   This vector is used to prevent a function call within an argument from
   clobbering any stack already set up.  */
static char *stack_usage_map;

/* Size of STACK_USAGE_MAP.  */
static int highest_outgoing_arg_in_use;
#endif

static void store_one_arg ();
extern enum machine_mode mode_for_size ();

/* Return 1 if EXP contains a call to the built-in function `alloca'.  */

static int
calls_alloca (exp)
     tree exp;
{
  register int i;
  int type = TREE_CODE_CLASS (TREE_CODE (exp));
  int length = tree_code_length[(int) TREE_CODE (exp)];

  /* Only expressions and references can contain calls.  */

  if (type != 'e' && type != '<' && type != '1' && type != '2' && type != 'r')
    return 0;

  switch (TREE_CODE (exp))
    {
    case CALL_EXPR:
      if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
	  && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
	      == FUNCTION_DECL)
	  && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
	  && (DECL_FUNCTION_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
	      == BUILT_IN_ALLOCA))
	return 1;

      /* Third operand is RTL.  */
      length = 2;
      break;

    case SAVE_EXPR:
      if (SAVE_EXPR_RTL (exp) != 0)
	return 0;
      break;

    case BLOCK:
      /* Must not look at BLOCK_SUPERCONTEXT since it will point back to
	 us.  */
      length = 3;
      break;

    case METHOD_CALL_EXPR:
      length = 3;
      break;

    case WITH_CLEANUP_EXPR:
      length = 1;
      break;

    case RTL_EXPR:
      return 0;
    }

  for (i = 0; i < length; i++)
    if (TREE_OPERAND (exp, i) != 0
	&& calls_alloca (TREE_OPERAND (exp, i)))
      return 1;

  return 0;
}

/* Force FUNEXP into a form suitable for the address of a CALL,
   and return that as an rtx.  Also load the static chain register
   if FNDECL is a nested function.

   USE_INSNS points to a variable holding a chain of USE insns
   to which a USE of the static chain
   register should be added, if required.  */

rtx
prepare_call_address (funexp, fndecl, use_insns)
     rtx funexp;
     tree fndecl;
     rtx *use_insns;
{
  rtx static_chain_value = 0;

  funexp = protect_from_queue (funexp, 0);

  if (fndecl != 0)
    /* Get possible static chain value for nested function in C. */
    static_chain_value = lookup_static_chain (fndecl);

  /* Make a valid memory address and copy constants thru pseudo-regs,
     but not for a constant address if -fno-function-cse.  */
  if (GET_CODE (funexp) != SYMBOL_REF)
    funexp = memory_address (FUNCTION_MODE, funexp);
  else
    {
#ifndef NO_FUNCTION_CSE
      if (optimize && ! flag_no_function_cse)
#ifdef NO_RECURSIVE_FUNCTION_CSE
	if (fndecl != current_function_decl)
#endif
	  funexp = force_reg (Pmode, funexp);
#endif
    }

  if (static_chain_value != 0)
    {
      emit_move_insn (static_chain_rtx, static_chain_value);

      /* Put the USE insn in the chain we were passed.  It will later be
	 output immediately in front of the CALL insn.  */
      push_to_sequence (*use_insns);
      emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
      *use_insns = get_insns ();
      end_sequence ();
    }

  return funexp;
}

/* Generate instructions to call function FUNEXP,
   and optionally pop the results.
   The CALL_INSN is the first insn generated.

   FUNTYPE is the data type of the function, or, for a library call,
   the identifier for the name of the call.  This is given to the
   macro RETURN_POPS_ARGS to determine whether this function pops its own args.

   STACK_SIZE is the number of bytes of arguments on the stack,
   rounded up to STACK_BOUNDARY; zero if the size is variable.
   This is both to put into the call insn and
   to generate explicit popping code if necessary.

   STRUCT_VALUE_SIZE is the number of bytes wanted in a structure value.
   It is zero if this call doesn't want a structure value.

   NEXT_ARG_REG is the rtx that results from executing
     FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1)
   just after all the args have had their registers assigned.
   This could be whatever you like, but normally it is the first
   arg-register beyond those used for args in this call,
   or 0 if all the arg-registers are used in this call.
   It is passed on to `gen_call' so you can put this info in the call insn.

   VALREG is a hard register in which a value is returned,
   or 0 if the call does not return a value.

   OLD_INHIBIT_DEFER_POP is the value that `inhibit_defer_pop' had before
   the args to this call were processed.
   We restore `inhibit_defer_pop' to that value.

   USE_INSNS is a chain of USE insns to be emitted immediately before
   the actual CALL insn.

   IS_CONST is true if this is a `const' call.  */

void
emit_call_1 (funexp, funtype, stack_size, struct_value_size, next_arg_reg,
	     valreg, old_inhibit_defer_pop, use_insns, is_const)
     rtx funexp;
     tree funtype;
     int stack_size;
     int struct_value_size;
     rtx next_arg_reg;
     rtx valreg;
     int old_inhibit_defer_pop;
     rtx use_insns;
     int is_const;
{
  rtx stack_size_rtx = gen_rtx (CONST_INT, VOIDmode, stack_size);
  rtx struct_value_size_rtx = gen_rtx (CONST_INT, VOIDmode, struct_value_size);
  rtx call_insn;
  int already_popped = 0;

  /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
     and we don't want to load it into a register as an optimization,
     because prepare_call_address already did it if it should be done.  */
  if (GET_CODE (funexp) != SYMBOL_REF)
    funexp = memory_address (FUNCTION_MODE, funexp);

#ifndef ACCUMULATE_OUTGOING_ARGS
#if defined (HAVE_call_pop) && defined (HAVE_call_value_pop)
  if (HAVE_call_pop && HAVE_call_value_pop
      && (RETURN_POPS_ARGS (funtype, stack_size) > 0 || stack_size == 0))
    {
      rtx n_pop = gen_rtx (CONST_INT, VOIDmode, 
			   RETURN_POPS_ARGS (funtype, stack_size));
      rtx pat;

      /* If this subroutine pops its own args, record that in the call insn
	 if possible, for the sake of frame pointer elimination.  */
      if (valreg)
	pat = gen_call_value_pop (valreg,
				  gen_rtx (MEM, FUNCTION_MODE, funexp),
				  stack_size_rtx, next_arg_reg, n_pop);
      else
	pat = gen_call_pop (gen_rtx (MEM, FUNCTION_MODE, funexp),
			    stack_size_rtx, next_arg_reg, n_pop);

      emit_call_insn (pat);
      already_popped = 1;
    }
  else
#endif
#endif

#if defined (HAVE_call) && defined (HAVE_call_value)
  if (HAVE_call && HAVE_call_value)
    {
      if (valreg)
	emit_call_insn (gen_call_value (valreg,
					gen_rtx (MEM, FUNCTION_MODE, funexp),
					stack_size_rtx, next_arg_reg));
      else
	emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, funexp),
				  stack_size_rtx, next_arg_reg,
				  struct_value_size_rtx));
    }
  else
#endif
    abort ();

  /* Find the CALL insn we just emitted and write the USE insns before it.  */
  for (call_insn = get_last_insn ();
       call_insn && GET_CODE (call_insn) != CALL_INSN;
       call_insn = PREV_INSN (call_insn))
    ;

  if (! call_insn)
    abort ();

  /* Put the USE insns before the CALL.  */
  emit_insns_before (use_insns, call_insn);

  /* If this is a const call, then set the insn's unchanging bit.  */
  if (is_const)
    CONST_CALL_P (call_insn) = 1;

  inhibit_defer_pop = old_inhibit_defer_pop;

#ifndef ACCUMULATE_OUTGOING_ARGS
  /* If returning from the subroutine does not automatically pop the args,
     we need an instruction to pop them sooner or later.
     Perhaps do it now; perhaps just record how much space to pop later.

     If returning from the subroutine does pop the args, indicate that the
     stack pointer will be changed.  */

  if (stack_size != 0 && RETURN_POPS_ARGS (funtype, stack_size) > 0)
    {
      if (!already_popped)
	emit_insn (gen_rtx (CLOBBER, VOIDmode, stack_pointer_rtx));
      stack_size -= RETURN_POPS_ARGS (funtype, stack_size);
      stack_size_rtx = gen_rtx (CONST_INT, VOIDmode, stack_size);
    }

  if (stack_size != 0)
    {
      if (flag_defer_pop && inhibit_defer_pop == 0)
	pending_stack_adjust += stack_size;
      else
	adjust_stack (stack_size_rtx);
    }
#endif
}

/* Generate all the code for a function call
   and return an rtx for its value.
   Store the value in TARGET (specified as an rtx) if convenient.
   If the value is stored in TARGET then TARGET is returned.
   If IGNORE is nonzero, then we ignore the value of the function call.  */

rtx
expand_call (exp, target, ignore, modifier)
     tree exp;
     rtx target;
     int ignore;
     enum expand_modifier modifier;
{
  /* List of actual parameters.  */
  tree actparms = TREE_OPERAND (exp, 1);
  /* RTX for the function to be called.  */
  rtx funexp;
  /* Tree node for the function to be called (not the address!).  */
  tree funtree;
  /* Data type of the function.  */
  tree funtype;
  /* Declaration of the function being called,
     or 0 if the function is computed (not known by name).  */
  tree fndecl = 0;
  char *name = 0;

  /* Register in which non-BLKmode value will be returned,
     or 0 if no value or if value is BLKmode.  */
  rtx valreg;
  /* Address where we should return a BLKmode value;
     0 if value not BLKmode.  */
  rtx structure_value_addr = 0;
  /* Nonzero if that address is being passed by treating it as
     an extra, implicit first parameter.  Otherwise,
     it is passed by being copied directly into struct_value_rtx.  */
  int structure_value_addr_parm = 0;
  /* Size of aggregate value wanted, or zero if none wanted
     or if we are using the non-reentrant PCC calling convention
     or expecting the value in registers.  */
  int struct_value_size = 0;
  /* Nonzero if called function returns an aggregate in memory PCC style,
     by returning the address of where to find it.  */
  int pcc_struct_value = 0;

  /* Number of actual parameters in this call, including struct value addr.  */
  int num_actuals;
  /* Number of named args.  Args after this are anonymous ones
     and they must all go on the stack.  */
  int n_named_args;
  /* Count arg position in order args appear.  */
  int argpos;

  /* Vector of information about each argument.
     Arguments are numbered in the order they will be pushed,
     not the order they are written.  */
  struct arg_data *args;

  /* Total size in bytes of all the stack-parms scanned so far.  */
  struct args_size args_size;
  /* Size of arguments before any adjustments (such as rounding).  */
  struct args_size original_args_size;
  /* Data on reg parms scanned so far.  */
  CUMULATIVE_ARGS args_so_far;
  /* Nonzero if a reg parm has been scanned.  */
  int reg_parm_seen;

  /* Nonzero if we must avoid push-insns in the args for this call. 
     If stack space is allocated for register parameters, but not by the
     caller, then it is preallocated in the fixed part of the stack frame.
     So the entire argument block must then be preallocated (i.e., we
     ignore PUSH_ROUNDING in that case).  */

#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
  int must_preallocate = 1;
#else
#ifdef PUSH_ROUNDING
  int must_preallocate = 0;
#else
  int must_preallocate = 1;
#endif
#endif

  /* 1 if scanning parms front to back, -1 if scanning back to front.  */
  int inc;
  /* Address of space preallocated for stack parms
     (on machines that lack push insns), or 0 if space not preallocated.  */
  rtx argblock = 0;

  /* Nonzero if it is plausible that this is a call to alloca.  */
  int may_be_alloca;
  /* Nonzero if this is a call to setjmp or a related function.  */
  int returns_twice;
  /* Nonzero if this is a call to `longjmp'.  */
  int is_longjmp;
  /* Nonzero if this is a call to an inline function.  */
  int is_integrable = 0;
  /* Nonzero if this is a call to __builtin_new.  */
  int is_builtin_new;
  /* Nonzero if this is a call to a `const' function.
     Note that only explicitly named functions are handled as `const' here.  */
  int is_const = 0;
  /* Nonzero if this is a call to a `volatile' function.  */
  int is_volatile = 0;
#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
  /* Define the boundary of the register parm stack space that needs to be
     save, if any.  */
  int low_to_save = -1, high_to_save;
  rtx save_area = 0;		/* Place that it is saved */
#endif

#ifdef ACCUMULATE_OUTGOING_ARGS
  int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
  char *initial_stack_usage_map = stack_usage_map;
#endif

  rtx old_stack_level = 0;
  int old_pending_adj;
  int old_inhibit_defer_pop = inhibit_defer_pop;
  tree old_cleanups = cleanups_this_call;

  rtx use_insns = 0;

  register tree p;
  register int i;

  /* See if we can find a DECL-node for the actual function.
     As a result, decide whether this is a call to an integrable function.  */

  p = TREE_OPERAND (exp, 0);
  if (TREE_CODE (p) == ADDR_EXPR)
    {
      fndecl = TREE_OPERAND (p, 0);
      if (TREE_CODE (fndecl) != FUNCTION_DECL)
	{
	  /* May still be a `const' function if it is
	     a call through a pointer-to-const.
	     But we don't handle that.  */
	  fndecl = 0;
	}
      else
	{
	  if (!flag_no_inline
	      && fndecl != current_function_decl
	      && DECL_SAVED_INSNS (fndecl))
	    is_integrable = 1;
	  else if (! TREE_ADDRESSABLE (fndecl))
	    {
	      /* In case this function later becomes inlineable,
		 record that there was already a non-inline call to it.

		 Use abstraction instead of setting TREE_ADDRESSABLE
		 directly.  */
	      if (TREE_INLINE (fndecl) && extra_warnings && !flag_no_inline)
		warning_with_decl (fndecl, "can't inline call to `%s' which was declared inline");
	      mark_addressable (fndecl);
	    }

	  if (TREE_READONLY (fndecl) && ! TREE_THIS_VOLATILE (fndecl)
	      && TYPE_MODE (TREE_TYPE (exp)) != VOIDmode)
	    is_const = 1;
	}
    }

  is_volatile = TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (p)));

  /* Warn if this value is an aggregate type,
     regardless of which calling convention we are using for it.  */
  if (warn_aggregate_return
      && (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
	  || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE
	  || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE))
    warning ("function call has aggregate value");

  /* Set up a place to return a structure.  */

  /* Cater to broken compilers.  */
  if (aggregate_value_p (exp))
    {
      /* This call returns a big structure.  */
      is_const = 0;

#ifdef PCC_STATIC_STRUCT_RETURN
      if (flag_pcc_struct_return)
	{
	  pcc_struct_value = 1;
	  is_integrable = 0;  /* Easier than making that case work right.  */
	}
      else
#endif
	{
	  struct_value_size = int_size_in_bytes (TREE_TYPE (exp));

	  if (struct_value_size < 0)
	    abort ();

	  if (target && GET_CODE (target) == MEM)
	    structure_value_addr = XEXP (target, 0);
	  else
	    {
	      /* Assign a temporary on the stack to hold the value.  */

	      /* For variable-sized objects, we must be called with a target
		 specified.  If we were to allocate space on the stack here,
		 we would have no way of knowing when to free it.  */

	      structure_value_addr
		= XEXP (assign_stack_temp (BLKmode, struct_value_size, 1), 0);
	      target = 0;
	    }
	}
    }

  /* If called function is inline, try to integrate it.  */

  if (is_integrable)
    {
      rtx temp;

      temp = expand_inline_function (fndecl, actparms, target,
				     ignore, TREE_TYPE (exp),
				     structure_value_addr);

      /* If inlining succeeded, return.  */
      if ((int) temp != -1)
	{
	  /* Perform all cleanups needed for the arguments of this call
	     (i.e. destructors in C++).  It is ok if these destructors
	     clobber RETURN_VALUE_REG, because the only time we care about
	     this is when TARGET is that register.  But in C++, we take
	     care to never return that register directly.  */
	  expand_cleanups_to (old_cleanups);

	  /* If the result is equivalent to TARGET, return TARGET to simplify
	     checks in store_expr.  They can be equivalent but not equal in the
	     case of a function that returns BLKmode.  */
	  if (temp != target && rtx_equal_p (temp, target))
	    return target;
	  return temp;
	}

      /* If inlining failed, mark FNDECL as needing to be compiled
	 separately after all.  */
      mark_addressable (fndecl);
    }

  /* When calling a const function, we must pop the stack args right away,
     so that the pop is deleted or moved with the call.  */
  if (is_const)
    NO_DEFER_POP;

  function_call_count++;

  if (fndecl && DECL_NAME (fndecl))
    name = IDENTIFIER_POINTER (DECL_NAME (fndecl));

#if 0
  /* Unless it's a call to a specific function that isn't alloca,
     if it has one argument, we must assume it might be alloca.  */

  may_be_alloca =
    (!(fndecl != 0 && strcmp (name, "alloca"))
     && actparms != 0
     && TREE_CHAIN (actparms) == 0);
#else
  /* We assume that alloca will always be called by name.  It
     makes no sense to pass it as a pointer-to-function to
     anything that does not understand its behavior.  */
  may_be_alloca =
    (name && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 6
		 && name[0] == 'a'
		 && ! strcmp (name, "alloca"))
		|| (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 16
		    && name[0] == '_'
		    && ! strcmp (name, "__builtin_alloca"))));
#endif

  /* See if this is a call to a function that can return more than once
     or a call to longjmp.  */

  returns_twice = 0;
  is_longjmp = 0;

  if (name != 0 && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 15)
    {
      char *tname = name;

      if (name[0] == '_')
	tname += ((name[1] == '_' && name[2] == 'x') ? 3 : 1);

      if (tname[0] == 's')
	{
	  returns_twice
	    = ((tname[1] == 'e'
		&& (! strcmp (tname, "setjmp")
		    || ! strcmp (tname, "setjmp_syscall")))
	       || (tname[1] == 'i'
		   && ! strcmp (tname, "sigsetjmp"))
	       || (tname[1] == 'a'
		   && ! strcmp (tname, "savectx")));
	  if (tname[1] == 'i'
	      && ! strcmp (tname, "siglongjmp"))
	    is_longjmp = 1;
	}
      else if ((tname[0] == 'q' && tname[1] == 's'
		&& ! strcmp (tname, "qsetjmp"))
	       || (tname[0] == 'v' && tname[1] == 'f'
		   && ! strcmp (tname, "vfork")))
	returns_twice = 1;

      else if (tname[0] == 'l' && tname[1] == 'o'
	       && ! strcmp (tname, "longjmp"))
	is_longjmp = 1;
    }

  is_builtin_new
    = (name != 0
       && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 13
       && (!strcmp (name, "__builtin_new")));

  if (may_be_alloca)
    current_function_calls_alloca = 1;

  /* Don't let pending stack adjusts add up to too much.
     Also, do all pending adjustments now
     if there is any chance this might be a call to alloca.  */

  if (pending_stack_adjust >= 32
      || (pending_stack_adjust > 0 && may_be_alloca))
    do_pending_stack_adjust ();

  /* Operand 0 is a pointer-to-function; get the type of the function.  */
  funtype = TREE_TYPE (TREE_OPERAND (exp, 0));
  if (TREE_CODE (funtype) != POINTER_TYPE)
    abort ();
  funtype = TREE_TYPE (funtype);

  /* Push the temporary stack slot level so that we can free temporaries used
     by each of the arguments separately.  */
  push_temp_slots ();

  /* Start updating where the next arg would go.  */
  INIT_CUMULATIVE_ARGS (args_so_far, funtype, 0);

  /* If struct_value_rtx is 0, it means pass the address
     as if it were an extra parameter.  */
  if (structure_value_addr && struct_value_rtx == 0)
    {
      actparms
	= tree_cons (error_mark_node,
		     make_tree (build_pointer_type (TREE_TYPE (funtype)),
				force_reg (Pmode, structure_value_addr)),
		     actparms);
      structure_value_addr_parm = 1;
    }

  /* Count the arguments and set NUM_ACTUALS.  */
  for (p = actparms, i = 0; p; p = TREE_CHAIN (p)) i++;
  num_actuals = i;

  /* Compute number of named args.
     Normally, don't include the last named arg if anonymous args follow.
     (If no anonymous args follow, the result of list_length
     is actually one too large.)

     If SETUP_INCOMING_VARARGS is defined, this machine will be able to
     place unnamed args that were passed in registers into the stack.  So
     treat all args as named.  This allows the insns emitting for a specific
     argument list to be independent of the function declaration.

     If SETUP_INCOMING_VARARGS is not defined, we do not have any reliable
     way to pass unnamed args in registers, so we must force them into
     memory.  */
#ifndef SETUP_INCOMING_VARARGS
  if (TYPE_ARG_TYPES (funtype) != 0)
    n_named_args
      = list_length (TYPE_ARG_TYPES (funtype)) - 1
	/* Count the struct value address, if it is passed as a parm.  */
	+ structure_value_addr_parm;
  else
#endif
    /* If we know nothing, treat all args as named.  */
    n_named_args = num_actuals;

  /* Make a vector to hold all the information about each arg.  */
  args = (struct arg_data *) alloca (num_actuals * sizeof (struct arg_data));
  bzero (args, num_actuals * sizeof (struct arg_data));

  args_size.constant = 0;
  args_size.var = 0;

  /* In this loop, we consider args in the order they are written.
     We fill up ARGS from the front of from the back if necessary
     so that in any case the first arg to be pushed ends up at the front.  */

#ifdef PUSH_ARGS_REVERSED
  i = num_actuals - 1, inc = -1;
  /* In this case, must reverse order of args
     so that we compute and push the last arg first.  */
#else
  i = 0, inc = 1;
#endif

  /* I counts args in order (to be) pushed; ARGPOS counts in order written.  */
  for (p = actparms, argpos = 0; p; p = TREE_CHAIN (p), i += inc, argpos++)
    {
      tree type = TREE_TYPE (TREE_VALUE (p));

      args[i].tree_value = TREE_VALUE (p);

      /* Replace erroneous argument with constant zero.  */
      if (type == error_mark_node || TYPE_SIZE (type) == 0)
	args[i].tree_value = integer_zero_node, type = integer_type_node;

      /* Decide where to pass this arg.

	 args[i].reg is nonzero if all or part is passed in registers.

	 args[i].partial is nonzero if part but not all is passed in registers,
	 and the exact value says how many words are passed in registers.

	 args[i].pass_on_stack is nonzero if the argument must at least be
	 computed on the stack.  It may then be loaded back into registers
	 if args[i].reg is nonzero.

	 These decisions are driven by the FUNCTION_... macros and must agree
	 with those made by function.c.  */

#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
      /* See if this argument should be passed by invisible reference.  */
      if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, TYPE_MODE (type), type,
					  argpos < n_named_args))
	{
	  /* We make a copy of the object and pass the address to the function
	     being called.  */
	  int size = int_size_in_bytes (type);
	  rtx copy;

	  if (size < 0)
	    {
	      /* This is a variable-sized object.  Make space on the stack
		 for it.  */
	      rtx size_rtx = expand_expr (size_in_bytes (type), 0,
					  VOIDmode, 0);

	      if (old_stack_level == 0)
		{
		  old_stack_level = copy_to_mode_reg (Pmode, stack_pointer_rtx);
		  old_pending_adj = pending_stack_adjust;
		  pending_stack_adjust = 0;
		}

	      copy = gen_rtx (MEM, BLKmode,
			      allocate_dynamic_stack_space (size_rtx, 0));
	    }
	  else
	    copy = assign_stack_temp (TYPE_MODE (type), size, 1);

	  store_expr (args[i].tree_value, copy, 0);

	  args[i].tree_value = build1 (ADDR_EXPR, build_pointer_type (type),
				       make_tree (type, copy));
	  type = build_pointer_type (type);
	}
#endif

      args[i].reg = FUNCTION_ARG (args_so_far, TYPE_MODE (type), type,
				  argpos < n_named_args);
#ifdef FUNCTION_ARG_PARTIAL_NREGS
      if (args[i].reg)
	args[i].partial
	  = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, TYPE_MODE (type), type,
					argpos < n_named_args);
#endif

      args[i].pass_on_stack = MUST_PASS_IN_STACK (TYPE_MODE (type), type);

      /* If FUNCTION_ARG returned an (expr_list (nil) FOO), it means that
	 we are to pass this arg in the register(s) designated by FOO, but
	 also to pass it in the stack.  */
      if (args[i].reg && GET_CODE (args[i].reg) == EXPR_LIST
	  && XEXP (args[i].reg, 0) == 0)
	args[i].pass_on_stack = 1, args[i].reg = XEXP (args[i].reg, 1);

      /* If this is an addressable type, we must preallocate the stack
	 since we must evaluate the object into its final location.

	 If this is to be passed in both registers and the stack, it is simpler
	 to preallocate.  */
      if (TREE_ADDRESSABLE (type)
	  || (args[i].pass_on_stack && args[i].reg != 0))
	must_preallocate = 1;

      /* If this is an addressable type, we cannot pre-evaluate it.  Thus,
	 we cannot consider this function call constant.  */
      if (TREE_ADDRESSABLE (type))
	is_const = 0;

      /* Compute the stack-size of this argument.  */
      if (args[i].reg == 0 || args[i].partial != 0
#ifdef REG_PARM_STACK_SPACE
	  || REG_PARM_STACK_SPACE (fndecl) > 0
#endif
	  || args[i].pass_on_stack)
	locate_and_pad_parm (TYPE_MODE (type), type,
#ifdef STACK_PARMS_IN_REG_PARM_AREA
			     1,
#else
			     args[i].reg != 0,
#endif
			     fndecl, &args_size, &args[i].offset,
			     &args[i].size);

#ifndef ARGS_GROW_DOWNWARD
      args[i].slot_offset = args_size;
#endif

#ifndef REG_PARM_STACK_SPACE
      /* If a part of the arg was put into registers,
	 don't include that part in the amount pushed.  */
      if (! args[i].pass_on_stack)
	args[i].size.constant -= ((args[i].partial * UNITS_PER_WORD)
				  / (PARM_BOUNDARY / BITS_PER_UNIT)
				  * (PARM_BOUNDARY / BITS_PER_UNIT));
#endif
      
      /* Update ARGS_SIZE, the total stack space for args so far.  */

      args_size.constant += args[i].size.constant;
      if (args[i].size.var)
	{
	  ADD_PARM_SIZE (args_size, args[i].size.var);
	}

      /* Since the slot offset points to the bottom of the slot,
	 we must record it after incrementing if the args grow down.  */
#ifdef ARGS_GROW_DOWNWARD
      args[i].slot_offset = args_size;

      args[i].slot_offset.constant = -args_size.constant;
      if (args_size.var)
	{
	  SUB_PARM_SIZE (args[i].slot_offset, args_size.var);
	}
#endif

      /* Increment ARGS_SO_FAR, which has info about which arg-registers
	 have been used, etc.  */

      FUNCTION_ARG_ADVANCE (args_so_far, TYPE_MODE (type), type,
			    argpos < n_named_args);
    }

  /* Compute the actual size of the argument block required.  The variable
     and constant sizes must be combined, the size may have to be rounded,
     and there may be a minimum required size.  */

  original_args_size = args_size;
  if (args_size.var)
    {
      /* If this function requires a variable-sized argument list, don't try to
	 make a cse'able block for this call.  We may be able to do this
	 eventually, but it is too complicated to keep track of what insns go
	 in the cse'able block and which don't.  */

      is_const = 0;
      must_preallocate = 1;

      args_size.var = ARGS_SIZE_TREE (args_size);
      args_size.constant = 0;

#ifdef STACK_BOUNDARY
      if (STACK_BOUNDARY != BITS_PER_UNIT)
	args_size.var = round_up (args_size.var, STACK_BYTES);
#endif

#ifdef REG_PARM_STACK_SPACE
      if (REG_PARM_STACK_SPACE (fndecl) > 0)
	{
	  args_size.var
	    = size_binop (MAX_EXPR, args_size.var,
			  size_int (REG_PARM_STACK_SPACE (fndecl)));

#ifndef OUTGOING_REG_PARM_STACK_SPACE
	  /* The area corresponding to register parameters is not to count in
	     the size of the block we need.  So make the adjustment.  */
	  args_size.var
	    = size_binop (MINUS_EXPR, args_size.var,
			  size_int (REG_PARM_STACK_SPACE (fndecl)));
#endif
	}
#endif
    }
  else
    {
#ifdef STACK_BOUNDARY
      args_size.constant = (((args_size.constant + (STACK_BYTES - 1))
			     / STACK_BYTES) * STACK_BYTES);
#endif

#ifdef REG_PARM_STACK_SPACE
      args_size.constant = MAX (args_size.constant,
				REG_PARM_STACK_SPACE (fndecl));
#ifndef OUTGOING_REG_PARM_STACK_SPACE
      args_size.constant -= REG_PARM_STACK_SPACE (fndecl);
#endif
#endif
    }

  /* See if we have or want to preallocate stack space.

     If we would have to push a partially-in-regs parm
     before other stack parms, preallocate stack space instead.

     If the size of some parm is not a multiple of the required stack
     alignment, we must preallocate.

     If the total size of arguments that would otherwise create a copy in
     a temporary (such as a CALL) is more than half the total argument list
     size, preallocation is faster.

     Another reason to preallocate is if we have a machine (like the m88k)
     where stack alignment is required to be maintained between every
     pair of insns, not just when the call is made.  However, we assume here
     that such machines either do not have push insns (and hence preallocation
     would occur anyway) or the problem is taken care of with
     PUSH_ROUNDING.  */

  if (! must_preallocate)
    {
      int partial_seen = 0;
      int copy_to_evaluate_size = 0;

      for (i = 0; i < num_actuals && ! must_preallocate; i++)
	{
	  if (args[i].partial > 0 && ! args[i].pass_on_stack)
	    partial_seen = 1;
	  else if (partial_seen && args[i].reg == 0)
	    must_preallocate = 1;

	  if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode
	      && (TREE_CODE (args[i].tree_value) == CALL_EXPR
		  || TREE_CODE (args[i].tree_value) == TARGET_EXPR
		  || TREE_CODE (args[i].tree_value) == COND_EXPR
		  || TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value))))
	    copy_to_evaluate_size
	      += int_size_in_bytes (TREE_TYPE (args[i].tree_value));
	}

      if (copy_to_evaluate_size >= args_size.constant / 2)
	must_preallocate = 1;
    }

  /* If the structure value address will reference the stack pointer, we must
     stabilize it.  We don't need to do this if we know that we are not going
     to adjust the stack pointer in processing this call.  */

  if (structure_value_addr
      && (reg_mentioned_p (virtual_stack_dynamic_rtx, structure_value_addr)
       || reg_mentioned_p (virtual_outgoing_args_rtx, structure_value_addr))
      && (args_size.var
#ifndef ACCUMULATE_OUTGOING_ARGS
	  || args_size.constant
#endif
	  ))
    structure_value_addr = copy_to_reg (structure_value_addr);

  /* If this function call is cse'able, precompute all the parameters.
     Note that if the parameter is constructed into a temporary, this will
     cause an additional copy because the parameter will be constructed
     into a temporary location and then copied into the outgoing arguments.
     If a parameter contains a call to alloca and this function uses the
     stack, precompute the parameter.  */

  for (i = 0; i < num_actuals; i++)
    if (is_const
	|| ((args_size.var != 0 || args_size.constant != 0)
	    && calls_alloca (args[i].tree_value)))
      {
	args[i].initial_value = args[i].value
	  = expand_expr (args[i].tree_value, 0, VOIDmode, 0);
	preserve_temp_slots (args[i].value);
	free_temp_slots ();

	/* ANSI doesn't require a sequence point here,
	   but PCC has one, so this will avoid some problems.  */
	emit_queue ();
      }

  /* Now we are about to start emitting insns that can be deleted
     if a libcall is deleted.  */
  if (is_const)
    start_sequence ();

  /* If we have no actual push instructions, or shouldn't use them,
     make space for all args right now.  */

  if (args_size.var != 0)
    {
      if (old_stack_level == 0)
	{
	  old_stack_level = copy_to_mode_reg (Pmode, stack_pointer_rtx);
	  old_pending_adj = pending_stack_adjust;
	  pending_stack_adjust = 0;
	}
      argblock = push_block (ARGS_SIZE_RTX (args_size), 0, 0);
    }
  else if (must_preallocate)
    {
      /* Note that we must go through the motions of allocating an argument
	 block even if the size is zero because we may be storing args
	 in the area reserved for register arguments, which may be part of
	 the stack frame.  */
      int needed = args_size.constant;

#ifdef ACCUMULATE_OUTGOING_ARGS
      /* Store the maximum argument space used.  It will be pushed by the
	 prologue.

	 Since the stack pointer will never be pushed, it is possible for
	 the evaluation of a parm to clobber something we have already
	 written to the stack.  Since most function calls on RISC machines
	 do not use the stack, this is uncommon, but must work correctly.
	 
	 Therefore, we save any area of the stack that was already written
	 and that we are using.  Here we set up to do this by making a new
	 stack usage map from the old one.  The actual save will be done
	 by store_one_arg. 

	 Another approach might be to try to reorder the argument
	 evaluations to avoid this conflicting stack usage.  */

      if (needed > current_function_outgoing_args_size)
	current_function_outgoing_args_size = needed;

#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
      /* Since we will be writing into the entire argument area, the
	 map must be allocated for its entire size, not just the part that
	 is the responsibility of the caller.  */
      needed += REG_PARM_STACK_SPACE (fndecl);
#endif

#ifdef ARGS_GROW_DOWNWARD
      highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
					 needed + 1);
#else
      highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, needed);
#endif
      stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use);

      if (initial_highest_arg_in_use)
	bcopy (initial_stack_usage_map, stack_usage_map,
	       initial_highest_arg_in_use);

      if (initial_highest_arg_in_use != highest_outgoing_arg_in_use)
	bzero (&stack_usage_map[initial_highest_arg_in_use],
	       highest_outgoing_arg_in_use - initial_highest_arg_in_use);
      needed = 0;
      /* No need to copy this virtual register; the space we're
	 using gets preallocated at the start of the function
	 so the stack pointer won't change here.  */
      argblock = virtual_outgoing_args_rtx;
#else /* not ACCUMULATE_OUTGOING_ARGS */
      if (inhibit_defer_pop == 0)
	{
	  /* Try to reuse some or all of the pending_stack_adjust
	     to get this space.  Maybe we can avoid any pushing.  */
	  if (needed > pending_stack_adjust)
	    {
	      needed -= pending_stack_adjust;
	      pending_stack_adjust = 0;
	    }
	  else
	    {
	      pending_stack_adjust -= needed;
	      needed = 0;
	    }
	}
      /* Special case this because overhead of `push_block' in this
	 case is non-trivial.  */
      if (needed == 0)
	argblock = virtual_outgoing_args_rtx;
      else
	argblock = push_block (gen_rtx (CONST_INT, VOIDmode, needed), 0, 0);

      /* We only really need to call `copy_to_reg' in the case where push
	 insns are going to be used to pass ARGBLOCK to a function
	 call in ARGS.  In that case, the stack pointer changes value
	 from the allocation point to the call point, and hence
	 the value of VIRTUAL_OUTGOING_ARGS_RTX changes as well.
	 But might as well always do it.  */
      argblock = copy_to_reg (argblock);
#endif /* not ACCUMULATE_OUTGOING_ARGS */
    }

  /* If we preallocated stack space, compute the address of each argument.
     We need not ensure it is a valid memory address here; it will be 
     validized when it is used.  */
  if (argblock)
    {
      rtx arg_reg = argblock;
      int arg_offset = 0;

      if (GET_CODE (argblock) == PLUS)
	arg_reg = XEXP (argblock, 0), arg_offset = INTVAL (XEXP (argblock, 1));

      for (i = 0; i < num_actuals; i++)
	{
	  rtx offset = ARGS_SIZE_RTX (args[i].offset);
	  rtx slot_offset = ARGS_SIZE_RTX (args[i].slot_offset);
	  rtx addr;

	  /* Skip this parm if it will not be passed on the stack.  */
	  if (! args[i].pass_on_stack && args[i].reg != 0)
	    continue;

	  if (GET_CODE (offset) == CONST_INT)
	    addr = plus_constant (arg_reg, INTVAL (offset));
	  else
	    addr = gen_rtx (PLUS, Pmode, arg_reg, offset);

	  addr = plus_constant (addr, arg_offset);
	  args[i].stack
	    = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (args[i].tree_value)), addr);

	  if (GET_CODE (slot_offset) == CONST_INT)
	    addr = plus_constant (arg_reg, INTVAL (slot_offset));
	  else
	    addr = gen_rtx (PLUS, Pmode, arg_reg, slot_offset);

	  addr = plus_constant (addr, arg_offset);
	  args[i].stack_slot
	    = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (args[i].tree_value)), addr);
	}
    }
					       
#ifdef PUSH_ARGS_REVERSED
#ifdef STACK_BOUNDARY
  /* If we push args individually in reverse order, perform stack alignment
     before the first push (the last arg).  */
  if (argblock == 0)
    anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode,
				(args_size.constant
				 - original_args_size.constant)));
#endif
#endif

  /* Don't try to defer pops if preallocating, not even from the first arg,
     since ARGBLOCK probably refers to the SP.  */
  if (argblock)
    NO_DEFER_POP;

  /* Get the function to call, in the form of RTL.  */
  if (fndecl)
    /* Get a SYMBOL_REF rtx for the function address.  */
    funexp = XEXP (DECL_RTL (fndecl), 0);
  else
    /* Generate an rtx (probably a pseudo-register) for the address.  */
    {
      funexp = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
      free_temp_slots ();	/* FUNEXP can't be BLKmode */
      emit_queue ();
    }

  /* Figure out the register where the value, if any, will come back.  */
  valreg = 0;
  if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode
      && ! structure_value_addr)
    {
      if (pcc_struct_value)
	valreg = hard_function_value (build_pointer_type (TREE_TYPE (exp)),
				      fndecl);
      else
	valreg = hard_function_value (TREE_TYPE (exp), fndecl);
    }

  /* Precompute all register parameters.  It isn't safe to compute anything
     once we have started filling any specific hard regs. */
  reg_parm_seen = 0;
  for (i = 0; i < num_actuals; i++)
    if (args[i].reg != 0 && ! args[i].pass_on_stack)
      {
	reg_parm_seen = 1;

	if (args[i].value == 0)
	  {
	    args[i].value = expand_expr (args[i].tree_value, 0, VOIDmode, 0);
	    preserve_temp_slots (args[i].value);
	    free_temp_slots ();

	    /* ANSI doesn't require a sequence point here,
	       but PCC has one, so this will avoid some problems.  */
	    emit_queue ();
	  }
      }

#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
  /* The argument list is the property of the called routine and it
     may clobber it.  If the fixed area has been used for previous
     parameters, we must save and restore it.

     Here we compute the boundary of the that needs to be saved, if any.  */

  for (i = 0; i < REG_PARM_STACK_SPACE (fndecl); i++)
    {
      if (i >=  highest_outgoing_arg_in_use
	  || stack_usage_map[i] == 0)
	continue;

      if (low_to_save == -1)
	low_to_save = i;

      high_to_save = i;
    }

  if (low_to_save >= 0)
    {
      int num_to_save = high_to_save - low_to_save + 1;
      enum machine_mode save_mode
	= mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
      rtx stack_area;

      /* If we don't have the required alignment, must do this in BLKmode.  */
      if ((low_to_save & (MIN (GET_MODE_SIZE (save_mode),
			       BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
	save_mode = BLKmode;

      stack_area = gen_rtx (MEM, save_mode,
			    memory_address (save_mode,
					    plus_constant (argblock,
							   low_to_save)));
      if (save_mode == BLKmode)
	{
	  save_area = assign_stack_temp (BLKmode, num_to_save, 1);
	  emit_block_move (validize_mem (save_area), stack_area,
			   gen_rtx (CONST_INT, VOIDmode, num_to_save),
			   PARM_BOUNDARY / BITS_PER_UNIT);
	}
      else
	{
	  save_area = gen_reg_rtx (save_mode);
	  emit_move_insn (save_area, stack_area);
	}
    }
#endif
	  

  /* Now store (and compute if necessary) all non-register parms.
     These come before register parms, since they can require block-moves,
     which could clobber the registers used for register parms.
     Parms which have partial registers are not stored here,
     but we do preallocate space here if they want that.  */

  for (i = 0; i < num_actuals; i++)
    if (args[i].reg == 0 || args[i].pass_on_stack)
      store_one_arg (&args[i], argblock, may_be_alloca,
		     args_size.var != 0, fndecl);

  /* Now store any partially-in-registers parm.
     This is the last place a block-move can happen.  */
  if (reg_parm_seen)
    for (i = 0; i < num_actuals; i++)
      if (args[i].partial != 0 && ! args[i].pass_on_stack)
	store_one_arg (&args[i], argblock, may_be_alloca,
		       args_size.var != 0, fndecl);

#ifndef PUSH_ARGS_REVERSED
#ifdef STACK_BOUNDARY
  /* If we pushed args in forward order, perform stack alignment
     after pushing the last arg.  */
  if (argblock == 0)
    anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode,
				(args_size.constant
				 - original_args_size.constant)));
#endif
#endif

  /* Pass the function the address in which to return a structure value.  */
  if (structure_value_addr && ! structure_value_addr_parm)
    {
      emit_move_insn (struct_value_rtx,
		      force_reg (Pmode,
				 force_operand (structure_value_addr, 0)));
      if (GET_CODE (struct_value_rtx) == REG)
	{
	  push_to_sequence (use_insns);
	  emit_insn (gen_rtx (USE, VOIDmode, struct_value_rtx));
	  use_insns = get_insns ();
	  end_sequence ();
	}
    }

  /* Now do the register loads required for any wholly-register parms or any
     parms which are passed both on the stack and in a register.  Their
     expressions were already evaluated. 

     Mark all register-parms as living through the call, putting these USE
     insns in a list headed by USE_INSNS.  */

  for (i = 0; i < num_actuals; i++)
    {
      rtx list = args[i].reg;
      int partial = args[i].partial;

      while (list)
	{
	  rtx reg;
	  int nregs;

	  /* Process each register that needs to get this arg.  */
	  if (GET_CODE (list) == EXPR_LIST)
	    reg = XEXP (list, 0), list = XEXP (list, 1);
	  else
	    reg = list, list = 0;

	  /* Set to non-zero if must move a word at a time, even if just one
	     word (e.g, partial == 1 && mode == DFmode).  Set to zero if
	     we just use a normal move insn.  */
	  nregs = (partial ? partial
		   : (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode
		      ? ((int_size_in_bytes (TREE_TYPE (args[i].tree_value))
			  + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
		      : 0));

	  /* If simple case, just do move.  If normal partial, store_one_arg
	     has already loaded the register for us.  In all other cases,
	     load the register(s) from memory.  */

	  if (nregs == 0)
	    emit_move_insn (reg, args[i].value);
	  else if (args[i].partial == 0 || args[i].pass_on_stack)
	    move_block_to_reg (REGNO (reg),
			       validize_mem (args[i].value), nregs,
			       TYPE_MODE (TREE_TYPE (args[i].tree_value)));
	
	  push_to_sequence (use_insns);
	  if (nregs == 0)
	    emit_insn (gen_rtx (USE, VOIDmode, reg));
	  else
	    use_regs (REGNO (reg), nregs);
	  use_insns = get_insns ();
	  end_sequence ();

	  /* PARTIAL referred only to the first register, so clear it for the
	     next time.  */
	  partial = 0;
	}
    }

  /* Perform postincrements before actually calling the function.  */
  emit_queue ();

  /* All arguments and registers used for the call must be set up by now!  */

  funexp = prepare_call_address (funexp, fndecl, &use_insns);

  /* Generate the actual call instruction.  */
  emit_call_1 (funexp, funtype, args_size.constant, struct_value_size,
	       FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
	       valreg, old_inhibit_defer_pop, use_insns, is_const);

  /* If call is cse'able, make appropriate pair of reg-notes around it.
     Test valreg so we don't crash; may safely ignore `const'
     if return type is void.  */
  if (is_const && valreg != 0)
    {
      rtx note = 0;
      rtx temp = gen_reg_rtx (GET_MODE (valreg));
      rtx insns;

      /* Construct an "equal form" for the value which mentions all the
	 arguments in order as well as the function name.  */
#ifdef PUSH_ARGS_REVERSED
      for (i = 0; i < num_actuals; i++)
	note = gen_rtx (EXPR_LIST, VOIDmode, args[i].initial_value, note);
#else
      for (i = num_actuals - 1; i >= 0; i--)
	note = gen_rtx (EXPR_LIST, VOIDmode, args[i].initial_value, note);
#endif
      note = gen_rtx (EXPR_LIST, VOIDmode, funexp, note);

      insns = get_insns ();
      end_sequence ();

      emit_libcall_block (insns, temp, valreg, note);

      valreg = temp;
    }

  /* For calls to `setjmp', etc., inform flow.c it should complain
     if nonvolatile values are live.  */

  if (returns_twice)
    {
      emit_note (name, NOTE_INSN_SETJMP);
      current_function_calls_setjmp = 1;
    }

  if (is_longjmp)
    current_function_calls_longjmp = 1;

  /* Notice functions that cannot return.
     If optimizing, insns emitted below will be dead.
     If not optimizing, they will exist, which is useful
     if the user uses the `return' command in the debugger.  */

  if (is_volatile || is_longjmp)
    emit_barrier ();

  /* For calls to __builtin_new, note that it can never return 0.
     This is because a new handler will be called, and 0 it not
     among the numbers it is supposed to return.  */
#if 0
  if (is_builtin_new)
    emit_note (name, NOTE_INSN_BUILTIN_NEW);
#endif

  /* If value type not void, return an rtx for the value.  */

  /* If there are cleanups to be called, don't use a hard reg as target.  */
  if (cleanups_this_call != old_cleanups
      && target && REG_P (target)
      && REGNO (target) < FIRST_PSEUDO_REGISTER)
    target = 0;

  if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode
      || ignore)
    {
      target = const0_rtx;
    }
  else if (structure_value_addr)
    {
      if (target == 0 || GET_CODE (target) != MEM)
	target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
			  memory_address (TYPE_MODE (TREE_TYPE (exp)),
					  structure_value_addr));
    }
  else if (pcc_struct_value)
    {
      if (target == 0)
	target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
			  copy_to_reg (valreg));
      else if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
	emit_move_insn (target, gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
					 copy_to_reg (valreg)));
      else
	emit_block_move (target, gen_rtx (MEM, BLKmode, copy_to_reg (valreg)),
			 expr_size (exp),
			 TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
    }
  else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)))
    /* TARGET and VALREG cannot be equal at this point because the latter
       would not have REG_FUNCTION_VALUE_P true, while the former would if
       it were referring to the same register.

       If they refer to the same register, this move will be a no-op, except
       when function inlining is being done.  */
    emit_move_insn (target, valreg);
  else
    target = copy_to_reg (valreg);

  /* Perform all cleanups needed for the arguments of this call
     (i.e. destructors in C++).  */
  expand_cleanups_to (old_cleanups);

  /* If size of args is variable, restore saved stack-pointer value.  */

  if (old_stack_level)
    {
      emit_move_insn (stack_pointer_rtx, old_stack_level);
      pending_stack_adjust = old_pending_adj;
    }

#ifdef ACCUMULATE_OUTGOING_ARGS
  else
    {
#ifdef REG_PARM_STACK_SPACE
      if (save_area)
	{
	  enum machine_mode save_mode = GET_MODE (save_area);
	  rtx stack_area
	    = gen_rtx (MEM, save_mode,
		       memory_address (save_mode,
				       plus_constant (argblock, low_to_save)));

	  if (save_mode != BLKmode)
	    emit_move_insn (stack_area, save_area);
	  else
	    emit_block_move (stack_area, validize_mem (save_area),
			     gen_rtx (CONST_INT, VOIDmode,
				      high_to_save - low_to_save + 1,
				      PARM_BOUNDARY / BITS_PER_UNIT));
	}
#endif
	  
      /* If we saved any argument areas, restore them.  */
      for (i = 0; i < num_actuals; i++)
	if (args[i].save_area)
	  {
	    enum machine_mode save_mode = GET_MODE (args[i].save_area);
	    rtx stack_area
	      = gen_rtx (MEM, save_mode,
			 memory_address (save_mode,
					 XEXP (args[i].stack_slot, 0)));

	    if (save_mode != BLKmode)
	      emit_move_insn (stack_area, args[i].save_area);
	    else
	      emit_block_move (stack_area, validize_mem (args[i].save_area),
			       gen_rtx (CONST_INT, VOIDmode,
					args[i].size.constant),
			       PARM_BOUNDARY / BITS_PER_UNIT);
	  }

      highest_outgoing_arg_in_use = initial_highest_arg_in_use;
      stack_usage_map = initial_stack_usage_map;
    }
#endif

  /* If this was alloca, record the new stack level for nonlocal gotos.  */
  if (may_be_alloca && nonlocal_goto_stack_level != 0)
    emit_move_insn (nonlocal_goto_stack_level, stack_pointer_rtx);

  pop_temp_slots ();

  return target;
}

#if 0
/* Return an rtx which represents a suitable home on the stack
   given TYPE, the type of the argument looking for a home.
   This is called only for BLKmode arguments.

   SIZE is the size needed for this target.
   ARGS_ADDR is the address of the bottom of the argument block for this call.
   OFFSET describes this parameter's offset into ARGS_ADDR.  It is meaningless
   if this machine uses push insns.  */

static rtx
target_for_arg (type, size, args_addr, offset)
     tree type;
     rtx size;
     rtx args_addr;
     struct args_size offset;
{
  rtx target;
  rtx offset_rtx = ARGS_SIZE_RTX (offset);

  /* We do not call memory_address if possible,
     because we want to address as close to the stack
     as possible.  For non-variable sized arguments,
     this will be stack-pointer relative addressing.  */
  if (GET_CODE (offset_rtx) == CONST_INT)
    target = plus_constant (args_addr, INTVAL (offset_rtx));
  else
    {
      /* I have no idea how to guarantee that this
	 will work in the presence of register parameters.  */
      target = gen_rtx (PLUS, Pmode, args_addr, offset_rtx);
      target = memory_address (QImode, target);
    }

  return gen_rtx (MEM, BLKmode, target);
}
#endif

/* Store a single argument for a function call
   into the register or memory area where it must be passed.
   *ARG describes the argument value and where to pass it.

   ARGBLOCK is the address of the stack-block for all the arguments,
   or 0 on a machine where arguments are pushed individually.

   MAY_BE_ALLOCA nonzero says this could be a call to `alloca'
   so must be careful about how the stack is used. 

   VARIABLE_SIZE nonzero says that this was a variable-sized outgoing
   argument stack.  This is used if ACCUMULATE_OUTGOING_ARGS to indicate
   that we need not worry about saving and restoring the stack.

   FNDECL is the declaration of the function we are calling.  */

static void
store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl)
     struct arg_data *arg;
     rtx argblock;
     int may_be_alloca;
     int variable_size;
     tree fndecl;
{
  register tree pval = arg->tree_value;
  rtx reg = 0;
  int partial = 0;
  int used = 0;
  int i, lower_bound, upper_bound;

  if (TREE_CODE (pval) == ERROR_MARK)
    return;

#ifdef ACCUMULATE_OUTGOING_ARGS
  /* If this is being stored into a pre-allocated, fixed-size, stack area,
     save any previous data at that location.  */
  if (argblock && ! variable_size && arg->stack)
    {
#ifdef ARGS_GROW_DOWNWARD
      /* stack_slot is negative, but we want to index stack_usage_map */
      /* with positive values. */
      if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS)
	upper_bound = -INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1)) + 1;
      else
	abort ();

      lower_bound = upper_bound - arg->size.constant;
#else
      if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS)
	lower_bound = INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1));
      else
	lower_bound = 0;

      upper_bound = lower_bound + arg->size.constant;
#endif

      for (i = lower_bound; i < upper_bound; i++)
	if (stack_usage_map[i]
#ifdef REG_PARM_STACK_SPACE
	    /* Don't store things in the fixed argument area at this point;
	       it has already been saved.  */
	    && i > REG_PARM_STACK_SPACE (fndecl)
#endif
	    )
	  break;

      if (i != upper_bound)
	{
	  /* We need to make a save area.  See what mode we can make it.  */
	  enum machine_mode save_mode
	    = mode_for_size (arg->size.constant * BITS_PER_UNIT, MODE_INT, 1);
	  rtx stack_area
	    = gen_rtx (MEM, save_mode,
		       memory_address (save_mode, XEXP (arg->stack_slot, 0)));

	  if (save_mode == BLKmode)
	    {
	      arg->save_area = assign_stack_temp (BLKmode,
						  arg->size.constant, 1);
	      emit_block_move (validize_mem (arg->save_area), stack_area,
			       gen_rtx (CONST_INT, VOIDmode,
					arg->size.constant),
			       PARM_BOUNDARY / BITS_PER_UNIT);
	    }
	  else
	    {
	      arg->save_area = gen_reg_rtx (save_mode);
	      emit_move_insn (arg->save_area, stack_area);
	    }
	}
    }
#endif

  /* If this isn't going to be placed on both the stack and in registers,
     set up the register and number of words.  */
  if (! arg->pass_on_stack)
    reg = arg->reg, partial = arg->partial;

  if (reg != 0 && partial == 0)
    /* Being passed entirely in a register.  We shouldn't be called in
       this case.   */
    abort ();

  /* If this is being partially passed in a register, but multiple locations
     are specified, we assume that the one partially used is the one that is
     listed first.  */
  if (reg && GET_CODE (reg) == EXPR_LIST)
    reg = XEXP (reg, 0);

  /* If this is being passes partially in a register, we can't evaluate
     it directly into its stack slot.  Otherwise, we can.  */
  if (arg->value == 0)
    arg->value = expand_expr (pval, partial ? 0 : arg->stack, VOIDmode, 0);

  /* Don't allow anything left on stack from computation
     of argument to alloca.  */
  if (may_be_alloca)
    do_pending_stack_adjust ();

  if (arg->value == arg->stack)
    /* If the value is already in the stack slot, we are done.  */
    ;
  else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode)
    {
      register int size;

      /* Argument is a scalar, not entirely passed in registers.
	 (If part is passed in registers, arg->partial says how much
	 and emit_push_insn will take care of putting it there.)
	 
	 Push it, and if its size is less than the
	 amount of space allocated to it,
	 also bump stack pointer by the additional space.
	 Note that in C the default argument promotions
	 will prevent such mismatches.  */

      size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval)));
      /* Compute how much space the push instruction will push.
	 On many machines, pushing a byte will advance the stack
	 pointer by a halfword.  */
#ifdef PUSH_ROUNDING
      size = PUSH_ROUNDING (size);
#endif
      used = size;

      /* Compute how much space the argument should get:
	 round up to a multiple of the alignment for arguments.  */
      if (none != FUNCTION_ARG_PADDING (TYPE_MODE (TREE_TYPE (pval)),
					TREE_TYPE (pval)))
	used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
		 / (PARM_BOUNDARY / BITS_PER_UNIT))
		* (PARM_BOUNDARY / BITS_PER_UNIT));

      /* This isn't already where we want it on the stack, so put it there.
	 This can either be done with push or copy insns.  */
      emit_push_insn (arg->value, TYPE_MODE (TREE_TYPE (pval)),
		      TREE_TYPE (pval), 0, 0, partial, reg,
		      used - size, argblock, ARGS_SIZE_RTX (arg->offset));
    }
  else
    {
      /* BLKmode, at least partly to be pushed.  */

      register int excess;
      rtx size_rtx;

      /* Pushing a nonscalar.
	 If part is passed in registers, PARTIAL says how much
	 and emit_push_insn will take care of putting it there.  */

      /* Round its size up to a multiple
	 of the allocation unit for arguments.  */

      if (arg->size.var != 0)
	{
	  excess = 0;
	  size_rtx = ARGS_SIZE_RTX (arg->size);
	}
      else
	{
	  register tree size = size_in_bytes (TREE_TYPE (pval));
	  /* PUSH_ROUNDING has no effect on us, because
	     emit_push_insn for BLKmode is careful to avoid it.  */
	  excess = (arg->size.constant - TREE_INT_CST_LOW (size)
		    + partial * UNITS_PER_WORD);
	  size_rtx = expand_expr (size, 0, VOIDmode, 0);
	}

      emit_push_insn (arg->value, TYPE_MODE (TREE_TYPE (pval)),
		      TREE_TYPE (pval), size_rtx,
		      TYPE_ALIGN (TREE_TYPE (pval)) / BITS_PER_UNIT, partial,
		      reg, excess, argblock, ARGS_SIZE_RTX (arg->offset));
    }


  /* Unless this is a partially-in-register argument, the argument is now
     in the stack. 

     ??? Note that this can change arg->value from arg->stack to
     arg->stack_slot and it matters when they are not the same.
     It isn't totally clear that this is correct in all cases.  */
  if (partial == 0)
    arg->value = arg->stack_slot;

  /* Once we have pushed something, pops can't safely
     be deferred during the rest of the arguments.  */
  NO_DEFER_POP;

  /* ANSI doesn't require a sequence point here,
     but PCC has one, so this will avoid some problems.  */
  emit_queue ();

  /* Free any temporary slots made in processing this argument.  */
  free_temp_slots ();

#ifdef ACCUMULATE_OUTGOING_ARGS
  /* Now mark the segment we just used.  */
  if (argblock && ! variable_size && arg->stack)
    for (i = lower_bound; i < upper_bound; i++)
      stack_usage_map[i] = 1;
#endif
}