Subversion Repositories tendra.SVN

Rev

Rev 2 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2 Rev 7
Line -... Line 1...
-
 
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
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
    
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
36
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
37
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
38
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
39
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
40
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
41
    shall be deemed to be acceptance of the following conditions:-
12
    
42
 
13
        (1) Its Recipients shall ensure that this Notice is
43
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
44
        reproduced upon any copies or amended versions of it;
15
    
45
 
16
        (2) Any amended version of it shall be clearly marked to
46
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
47
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
48
        for the relevant amendment or amendments;
19
    
49
 
20
        (3) Its onward transfer from a recipient to another
50
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
51
        party shall be deemed to be that party's acceptance of
22
        these conditions;
52
        these conditions;
23
    
53
 
24
        (4) DERA gives no warranty or assurance as to its
54
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
55
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
56
        no liability whatsoever in relation to any use to which
27
        it may be put.
57
        it may be put.
28
*/
58
*/
29
 
59
 
30
 
60
 
31
/* 	$Id: weights.c,v 1.1.1.1 1998/01/17 15:56:01 release Exp $	 */
61
/* 	$Id$	 */
32
 
62
 
33
#ifndef lint
63
#ifndef lint
34
static char vcid[] = "$Id: weights.c,v 1.1.1.1 1998/01/17 15:56:01 release Exp $";
64
static char vcid[] = "$Id$";
35
#endif /* lint */
65
#endif /* lint */
36
 
66
 
37
/*
67
/*
38
   weights.c
68
   weights.c
39
 
69
 
40
   The main procedure here is weightsv which determines the 
70
   The main procedure here is weightsv which determines the
41
   allocation of s regs. It considers which of those tags not 
71
   allocation of s regs. It considers which of those tags not
42
   already allocated to a t reg by scan, are best put in an s 
72
   already allocated to a t reg by scan, are best put in an s
43
   register. The same conditions as for t regs apply as to the 
73
   register. The same conditions as for t regs apply as to the
44
   suitability of the tags for registers.  Weights estimates the 
74
   suitability of the tags for registers.  Weights estimates the
45
   usage of each tag and hence the amount that would be saved if 
75
   usage of each tag and hence the amount that would be saved if
46
   it were held in an s reg. Thus it computes break points for
76
   it were held in an s reg. Thus it computes break points for
47
   register allocation for later use by reg_alloc.  The type 
77
   register allocation for later use by reg_alloc.  The type
48
   weights consists of two arrays of integers. In the first array 
78
   weights consists of two arrays of integers. In the first array
49
   each integer corresponds to a fixpnt reg and the second arrays'
79
   each integer corresponds to a fixpnt reg and the second arrays'
50
   integers correspond to floating point regs.  At the end of a 
80
   integers correspond to floating point regs.  At the end of a
51
   call of weights on an ident exp the props field of the ident 
81
   call of weights on an ident exp the props field of the ident
52
   may still contain inreg_bits or infreg_bits, set by scan, to 
82
   may still contain inreg_bits or infreg_bits, set by scan, to
53
   indicate that a t reg should be used. Otherwise number of ident 
83
   indicate that a t reg should be used. Otherwise number of ident
54
   is set up to represent the break point for allocation. A similar 
84
   is set up to represent the break point for allocation. A similar
55
   process occurs for proc parameters which have the break value 
85
   process occurs for proc parameters which have the break value
56
   in the forweights field of the parapair of the corresponding 
86
   in the forweights field of the parapair of the corresponding
57
   procrec. This value has three meanings:
87
   procrec. This value has three meanings:
58
 
88
 
59
   1) The ident (or parameter) defines a fixpnt value and number
89
   1) The ident (or parameter) defines a fixpnt value and number
60
   of ident (forweights of parpair) is an integer brk with the 
90
   of ident (forweights of parpair) is an integer brk with the
61
   interpretation that if there are at least brk fixpt s registers 
91
   interpretation that if there are at least brk fixpt s registers
62
   unallocated at this point then one will be used for this tag 
92
   unallocated at this point then one will be used for this tag
63
   (parameter).
93
   (parameter).
64
 
94
 
65
   2) As 1 but for floating point values.
95
   2) As 1 but for floating point values.
66
	
96
 
67
   3) number of ident = 100 in which case allocate value on the 
97
   3) number of ident = 100 in which case allocate value on the
68
   stack, (this is obviously always available for parameters).
98
   stack, (this is obviously always available for parameters).
69
 
99
 
70
*/
100
*/
71
 
101
 
72
/*
102
/*
Line 116... Line 146...
116
{
146
{
117
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
147
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
118
}
148
}
119
};
149
};
120
 
150
 
121
weights weightsv PROTO_S ((double scale, exp e));
151
weights weightsv(double scale, exp e);
122
 
152
 
123
weights add_weights
153
weights add_weights
124
    PROTO_N ( ( w1,w2 ) )
-
 
125
    PROTO_T ( weights *w1 X weights *w2 )
154
(weights *w1, weights *w2)
126
{
155
{
127
  /* sum of weights*/
156
  /* sum of weights*/
128
  weights r;
157
  weights r;
129
  long  i;
158
  long  i;
130
  for (i = 0; i < wfixno; ++i) {
159
  for (i = 0; i < wfixno; ++i) {
131
    (r.fix)[i] = (w1->fix)[i]+(w2->fix)[i];
160
   (r.fix)[i] = (w1->fix)[i] + (w2->fix)[i];
132
  };
161
  };
133
  for (i = 0; i < wfloatno; ++i) {
162
  for (i = 0; i < wfloatno; ++i) {
134
    (r.floating)[i] = (w1->floating)[i]+(w2->floating)[i];
163
   (r.floating)[i] = (w1->floating)[i] + (w2->floating)[i];
135
  };
164
  };
136
  return (r);
165
  return(r);
137
}
166
}
138
 
167
 
139
 
168
 
140
 
169
 
141
/* loc is the usage count of a tag, ws is
170
/* loc is the usage count of a tag, ws is
Line 149... Line 178...
149
   tag into a reg ("regged"). This proc is
178
   tag into a reg ("regged"). This proc is
150
   the source of all non-zero weights. NB
179
   the source of all non-zero weights. NB
151
   loc may be negative since using a s-reg
180
   loc may be negative since using a s-reg
152
   will involve a dump and restore  */
181
   will involve a dump and restore  */
153
wp max_weights
182
wp max_weights
154
    PROTO_N ( ( loc, ws, fix ) )
-
 
155
    PROTO_T ( double loc X weights * ws X bool fix )
183
(double loc, weights * ws, bool fix)
156
{
184
{
157
 
185
 
158
  long  bk = wfixno + 1;
186
  long  bk = wfixno + 1;
159
 
187
 
160
  long  i;
188
  long  i;
161
  float *w = (ws -> fix);
189
  float *w = (ws -> fix);
162
  /*  w[i] = greatest usage of (i+1) inner fixed tags  */
190
  /*  w[i] = greatest usage of (i+1) inner fixed tags  */
163
  wp res;
191
  wp res;
164
  float *pw = &(((res.wp_weights).fix)[0]);
192
  float *pw = & (((res.wp_weights).fix)[0]);
165
  if (fix) {
193
  if (fix) {
166
    for (i = 0; i < wfixno; ++i) {
194
    for (i = 0; i < wfixno; ++i) {
167
      if (i == 0) {
195
      if (i == 0) {
168
	if (loc > w[i]) {
196
	if (loc > w[i]) {
169
	  /* this tag has higher usage than any inner one ... */
197
	  /* this tag has higher usage than any inner one ... */
Line 173... Line 201...
173
	else
201
	else
174
	  pw[i] = w[i];
202
	  pw[i] = w[i];
175
      }
203
      }
176
      else {
204
      else {
177
	if ((loc + w[i - 1]) > w[i]) {
205
	if ((loc + w[i - 1]) > w[i]) {
178
	  /* this tag and i inner ones have higher usage than any other 
206
	  /* this tag and i inner ones have higher usage than any other
179
	     (i+1) inner ones ... */
207
	     (i+1) inner ones ... */
180
	  pw[i] = loc + w[i - 1];
208
	  pw[i] = loc + w[i - 1];
181
	  if (i < bk)
209
	  if (i < bk)
182
	    bk = i;
210
	    bk = i;
183
	  /* ... so it and i inner ones are regged in preference to any
211
	  /* ... so it and i inner ones are regged in preference to any
Line 190... Line 218...
190
 
218
 
191
    res.fix_break = bk;
219
    res.fix_break = bk;
192
  }
220
  }
193
  else {
221
  else {
194
    for (i = 0; i < wfixno; ++i) {
222
    for (i = 0; i < wfixno; ++i) {
195
      pw[i] = w[i];
223
      pw[i] = w[i];
196
    }
224
    }
197
  }
225
  }
198
 
226
 
199
  res.fix_break = bk;
227
  res.fix_break = bk;
200
 
228
 
201
  bk = wfloatno + 1;
229
  bk = wfloatno + 1;
202
  w = (ws -> floating);
230
  w = (ws -> floating);
203
  pw = &(((res.wp_weights).floating)[0]);
231
  pw = & (((res.wp_weights).floating)[0]);
204
  if (!fix) {			/* same algorithm for float regs as fixed
232
  if (!fix) {			/* same algorithm for float regs as fixed
205
				   regs */
233
				   regs */
206
    for (i = 0; i < wfloatno; ++i) {
234
    for (i = 0; i < wfloatno; ++i) {
207
      if (i == 0) {
235
      if (i == 0) {
208
	if (loc > w[i]) {
236
	if (loc > w[i]) {
209
	  pw[i] = loc;
237
	  pw[i] = loc;
210
	  bk = i;
238
	  bk = i;
211
	}
239
	}
Line 226... Line 254...
226
  else {
254
  else {
227
    for (i = 0; i < wfloatno; ++i) {
255
    for (i = 0; i < wfloatno; ++i) {
228
      pw[i] = w[i];
256
      pw[i] = w[i];
229
    }
257
    }
230
  }
258
  }
231
 
259
 
232
  res.float_break = bk;
260
  res.float_break = bk;
233
  return res;
261
  return res;
234
}
262
}
235
 
263
 
236
weights mult_weights
264
weights mult_weights
237
    PROTO_N ( ( m,ws ) )
-
 
238
    PROTO_T ( double m X weights *ws )
265
(double m, weights *ws)
239
{
266
{
240
  /* multiply weights by scalar - non
267
  /* multiply weights by scalar - non
241
     overflowing */
268
     overflowing */
242
  weights res;
269
  weights res;
243
  float *r = &(res.fix)[0];
270
  float *r = & (res.fix)[0];
244
  float *w = ws -> fix;
271
  float *w = ws -> fix;
245
  long  i;
272
  long  i;
246
  for (i = 0; i < wfixno; ++i) {
273
  for (i = 0; i < wfixno; ++i) {
247
      r[i] = w[i] * m;
274
      r[i] = w[i]* m;
248
  };
275
  };
249
 
276
 
250
  r = &(res.floating)[0];
277
  r = & (res.floating)[0];
251
  w = ws -> floating;
278
  w = ws -> floating;
252
  for (i = 0; i < wfloatno; ++i) {
279
  for (i = 0; i < wfloatno; ++i) {
253
      r[i] = w[i] * m;
280
      r[i] = w[i]* m;
254
  };
281
  };
255
  return (res);
282
  return(res);
256
}
283
}
257
 
284
 
258
weights add_wlist
285
weights add_wlist
259
    PROTO_N ( ( scale, re ) )
-
 
260
    PROTO_T ( double scale X exp re )
286
(double scale, exp re)
261
{
287
{
262
  weights w, w1;
288
  weights w, w1;
263
  exp r = re;
289
  exp r = re;
264
  if (r == nilexp) {
290
  if (r == nilexp) {
265
    return zeroweights;
291
    return zeroweights;
266
  }
292
  }
267
  else
293
  else
268
    if (last (r)) {
294
    if (last(r)) {
269
      return (weightsv (scale, r));
295
      return(weightsv(scale, r));
270
    }
296
    }
271
    else {
297
    else {
272
      w = weightsv (scale, r);
298
      w = weightsv(scale, r);
273
      Assert(r != bro(r));
299
      Assert(r != bro(r));
274
      do {
300
      do {
275
	r = bro (r);
301
	r = bro(r);
276
	w1 = weightsv (scale, r);
302
	w1 = weightsv(scale, r);
277
	w = add_weights (&w, &w1);
303
	w = add_weights(&w, &w1);
278
      } while (!last (r));
304
      } while (!last(r));
279
      return w;
305
      return w;
280
    }
306
    }
281
}
307
}
282
 
308
 
283
 
309
 
284
 
310
 
285
/*
311
/*
286
   weightsv
312
   weightsv
287
 
313
 
288
   This procedure estimates the usage of tags and parameters to 
314
   This procedure estimates the usage of tags and parameters to
289
   help determine whether they can advantageously be placed in 
315
   help determine whether they can advantageously be placed in
290
   s registers.  The parameter scale allows more importance to 
316
   s registers.  The parameter scale allows more importance to
291
   be placed on usage inside 'for' loops for example. The 
317
   be placed on usage inside 'for' loops for example. The
292
   procedure reg_alloc in reg_alloc.c finally determines the 
318
   procedure reg_alloc in reg_alloc.c finally determines the
293
   actual choice of s reg and recodes the number field of an ident. 
319
   actual choice of s reg and recodes the number field of an ident.
294
*/
320
*/
295
weights weightsv
321
weights weightsv
296
    PROTO_N ( ( scale, e ) )
-
 
297
    PROTO_T ( double scale X exp e )
322
(double scale, exp e)
298
{
323
{
299
 unsigned char  n;
324
 unsigned char  n;
300
 tailrecurse: 
325
 tailrecurse:
301
  n = name (e);
326
  n = name(e);
302
  switch (n) {
327
  switch (n) {
303
    case name_tag: 
328
    case name_tag:
304
      {
329
      {
305
	exp s = son (e);
330
	exp s = son(e);
306
	if (name (s) == ident_tag && !isglob (s)) {
331
	if (name(s) == ident_tag && !isglob(s)) {
307
	  if (is_floating(name(sh(e))) && name(sh(e)) != shrealhd) {
332
	  if (is_floating(name(sh(e))) && name(sh(e))!= shrealhd) {
308
	  	fno(s) += scale*2.0;
333
	  	fno(s) += scale*2.0;
309
	  } else fno (s) += scale;
334
	  } else fno(s) += scale;
310
	}
335
	}
311
	/* usage of tag stored in number of son of load_name (decl) */
336
	/* usage of tag stored in number of son of load_name (decl) */
312
	return zeroweights;
337
	return zeroweights;
313
      }
338
      }
314
 
339
 
315
    case ident_tag: 
340
    case ident_tag:
316
      {
341
      {
317
	if (son (e) != nilexp) {
342
	if (son(e)!= nilexp) {
318
	  weights wdef;
343
	  weights wdef;
319
	  weights wbody;
344
	  weights wbody;
320
	  long  noe = no (e) /* set by scan */ ;
345
	  long  noe = no (e) /* set by scan */ ;
321
	  if ((name (son (e)) == clear_tag) || (props (e) & defer_bit)) {
346
	  if ((name(son(e)) == clear_tag) || (props(e) & defer_bit)) {
322
	    wdef = zeroweights;
347
	    wdef = zeroweights;
323
	    fno(e)= 0.0;
348
	    fno(e) = 0.0;
324
	  }
349
	  }
325
	  else {
350
	  else {
326
	    /* maybe needs a store to initialise */ 
351
	    /* maybe needs a store to initialise */
327
	    if (is_floating(name(sh(son(e)))) && name(sh(son(e))) != shrealhd) {
352
	    if (is_floating(name(sh(son(e)))) && name(sh(son(e)))!= shrealhd) {
328
	  		fno(e) = scale*2.0;
353
	  		fno(e) = scale*2.0;
329
	    } else fno (e) = scale;	    	    
354
	    } else fno(e) = scale;
330
	    wdef = weightsv (scale, son (e));
355
	    wdef = weightsv(scale, son(e));
331
	  }
356
	  }
332
	  /* weights for initialisation of dec */
357
	  /* weights for initialisation of dec */
333
 
358
 
334
	  wbody = weightsv (scale, bro (son (e)));
359
	  wbody = weightsv(scale, bro(son(e)));
335
	  /* weights of body of scan */
360
	  /* weights of body of scan */
336
	  
361
 
337
	  if (props (e) & defer_bit) {/* declaration will be treated
362
	  if (props (e) & defer_bit) {/* declaration will be treated
338
				   transparently in code production */
363
				   transparently in code production */
339
	    exp t = son (e);
364
	    exp t = son(e);
340
	    exp s;
365
	    exp s;
341
	    if (name (t) == val_tag || name(t) == real_tag) {
366
	    if (name(t) == val_tag || name(t) == real_tag) {
342
	      return wbody;
367
	      return wbody;
343
	    }
368
	    }
344
	    while (name (t) != name_tag) {
369
	    while (name(t)!= name_tag) {
345
	      t = son (t);
370
	      t = son(t);
346
	    }
371
	    }
347
 
372
 
348
	    s = son (t);
373
	    s = son(t);
349
	    if (name (s) == ident_tag && !isglob (t)){
374
	    if (name(s) == ident_tag && !isglob(t)) {
350
	      fno (s) = fno (e);	/* is this correct */
375
	      fno (s) = fno (e);	/* is this correct */
351
	    }
376
	    }
352
	    /* usage of tag stored in number of son of 
377
	    /* usage of tag stored in number of son of
353
	     load_name (decl) */
378
	     load_name (decl) */
354
 
379
 
355
	    return wbody;
380
	    return wbody;
356
	  }			/* end deferred */
381
	  }			/* end deferred */
357
 
382
 
358
	  if ((props (e) & inreg_bits) == 0 && fixregable (e)) {
383
	  if ((props(e) & inreg_bits) == 0 && fixregable(e)) {
359
	    wp p;
384
	    wp p;
360
	    p = max_weights (fno (e) - 2.0*scale , &wbody, 1);
385
	    p = max_weights(fno(e) - 2.0*scale , &wbody, 1);
361
	    /* usage decreased by 2 because of dump and 
386
	    /* usage decreased by 2 because of dump and
362
	       restore of s-reg 
387
	       restore of s-reg
363
	    */
388
	    */
364
	    no (e) = p.fix_break;
389
	    no(e) = p.fix_break;
365
	    return (add_weights (&wdef, &p.wp_weights));
390
	    return(add_weights(&wdef, &p.wp_weights));
366
	  }
391
	  }
367
	  else if ((props (e) & infreg_bits) == 0 && floatregable (e)) {
392
	  else if ((props(e) & infreg_bits) == 0 && floatregable(e)) {
368
	    wp p;
393
	    wp p;
369
	    p = max_weights (fno (e) - 2 * scale, &wbody, 0);
394
	    p = max_weights(fno(e) - 2 * scale, &wbody, 0);
370
	    /* usage decreased by 4(on mips) because of dump 
395
	    /* usage decreased by 4(on mips) because of dump
371
	       and restore of double s-reg */
396
	       and restore of double s-reg */
372
	    no (e) = p.float_break;
397
	    no(e) = p.float_break;
373
	    return (add_weights (&wdef, &p.wp_weights));
398
	    return(add_weights(&wdef, &p.wp_weights));
374
	  }
399
	  }
375
	  else {
400
	  else {
376
	    no (e) = noe /* restore to value given by scan */ ;
401
	    no (e) = noe /* restore to value given by scan */ ;
377
	    return add_weights (&wdef, &wbody);
402
	    return add_weights(&wdef, &wbody);
378
	  }
403
	  }
379
	}	
404
	}
380
	else
405
	else
381
	  return zeroweights;
406
	  return zeroweights;
382
      };
407
      };
383
    case rep_tag: {
408
    case rep_tag: {
384
	e = bro (son (e));
409
	e = bro(son(e));
385
	goto tailrecurse;
410
	goto tailrecurse;
386
      }
411
      }
387
 
412
 
388
    case case_tag: {
413
    case case_tag: {
389
	e = son (e);
414
	e = son(e);
390
	goto tailrecurse;
415
	goto tailrecurse;
391
      };
416
      };
392
 
417
 
393
    case labst_tag: {
418
    case labst_tag: {
394
      scale = fno(e);
419
      scale = fno(e);
395
      e = bro (son (e));
420
      e = bro(son(e));
396
      goto tailrecurse;
421
      goto tailrecurse;
397
    }
422
    }
398
 
423
 
399
 
424
 
400
    case val_tag:{
425
    case val_tag:{
401
	return zeroweights;
426
	return zeroweights;
402
      };
427
      };
Line 409... Line 434...
409
    case seq_tag: {
434
    case seq_tag: {
410
      exp l = son(son(e));
435
      exp l = son(son(e));
411
      exp r = bro(son(e));
436
      exp r = bro(son(e));
412
      weights w,w1;
437
      weights w,w1;
413
      w = weightsv(scale,l);
438
      w = weightsv(scale,l);
414
      while(!last(l)){
439
      while (!last(l)) {
415
	l = bro(l);
440
	l = bro(l);
416
	w1 = weightsv(scale,l);
441
	w1 = weightsv(scale,l);
417
	w = add_weights(&w,&w1);
442
	w = add_weights(&w,&w1);
418
      }
443
      }
419
      w1 = weightsv(scale,r);
444
      w1 = weightsv(scale,r);
420
      w = add_weights(&w,&w1);
445
      w = add_weights(&w,&w1);
421
      return w;
446
      return w;
422
    }
447
    }
423
      
448
 
424
     default: {
449
     default: {
425
       if (son (e) == nilexp || n == env_offset_tag || 
450
       if (son(e) == nilexp || n == env_offset_tag ||
426
	   n == general_env_offset_tag) {
451
	   n == general_env_offset_tag) {
427
	 return zeroweights;
452
	 return zeroweights;
428
	}
453
	}
429
       if (last (son (e))) {
454
       if (last(son(e))) {
430
	 e = son (e);
455
	 e = son(e);
431
	 goto tailrecurse;
456
	 goto tailrecurse;
432
       }
457
       }
433
       return (add_wlist (scale, son (e)));
458
       return(add_wlist(scale, son(e)));
434
     }
459
     }
435
    }
460
    }
436
}
461
}
437
 
462
 
438
 
463