1 /* $Id: local.c,v 1.15 2008/12/14 21:16:58 ragge Exp $ */
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 /* this file contains code which is dependent on the target machine */
37 /* this is called to do local transformations on
38 an expression tree preparitory to its being
39 written out in intermediate code.
42 /* the major essential job is rewriting the
43 automatic variables and arguments in terms of
45 /* conversion ops which are not necessary are also clobbered here */
46 /* in addition, any special features (such as rewriting
47 exclusive or) are easily handled here as well */
54 switch( o
= p
->n_op
){
57 if ((q
= p
->n_sp
) == NULL
)
58 return p
; /* Nothing to care about */
64 /* fake up a structure reference */
65 r
= block(REG
, NIL
, NIL
, PTR
+STRTY
, 0, 0);
68 p
= stref(block(STREF
, r
, p
, 0, 0, 0));
81 p
->n_rval
= q
->soffset
;
89 if( p
->n_right
->n_op
!= ICON
) cerror( "bad conversion", 0);
91 return(buildtree(o
==PMCONV
?MUL
:DIV
, p
->n_left
, p
->n_right
));
94 ml
= p
->n_left
->n_type
;
96 if ((ml
== CHAR
|| ml
== UCHAR
) && l
->n_op
!= ICON
)
98 l
->n_type
= p
->n_type
;
99 l
->n_qual
= p
->n_qual
;
108 if (DEUNSIGN(p
->n_type
) == INT
&& DEUNSIGN(l
->n_type
) == INT
) {
112 if (l
->n_op
== ICON
) {
113 CONSZ val
= l
->n_lval
;
116 l
->n_lval
= (char)val
;
119 l
->n_lval
= val
& 0377;
123 l
->n_lval
= (short)val
;
127 l
->n_lval
= val
& 0177777;
131 l
->n_lval
= val
& 0xffffffff;
135 l
->n_lval
= (int)val
;
146 cerror("unknown type %d", p
->n_type
);
148 l
->n_type
= p
->n_type
;
164 return(1); /* all names can have & taken on them */
168 * at the end of the arguments of a ftn, set the automatic offset
177 * is an automatic variable of type t OK for a register variable
182 if (t
== INT
|| t
== UNSIGNED
|| t
== CHAR
|| t
== UCHAR
||
185 return 0; /* XXX - fix reg assignment in pftn.c */
189 * return a node, for structure references, which is suitable for
190 * being added to a pointer of type t, in order to be off bits offset
192 * t, d, and s are the type, dimension offset, and sizeoffset
193 * For pdp10, return the type-specific index number which calculation
194 * is based on its size. For example, short a[3] would return 3.
195 * Be careful about only handling first-level pointers, the following
196 * indirections must be fullword.
199 offcon(OFFSZ off
, TWORD t
, union dimfun
*d
, struct suedef
*sue
)
204 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
205 off
, t
, d
, sue
->suesize
);
208 p
->n_lval
= off
/SZCHAR
; /* Default */
213 * Allocate off bits on the stack. p is a tree that when evaluated
214 * is the multiply count for off, t is a NAME node where to write
215 * the allocated address.
218 spalloc(NODE
*t
, NODE
*p
, OFFSZ off
)
222 if ((off
% SZINT
) == 0)
223 p
= buildtree(MUL
, p
, bcon(off
/SZINT
));
224 else if ((off
% SZSHORT
) == 0) {
225 p
= buildtree(MUL
, p
, bcon(off
/SZSHORT
));
226 p
= buildtree(PLUS
, p
, bcon(1));
227 p
= buildtree(RS
, p
, bcon(1));
228 } else if ((off
% SZCHAR
) == 0) {
229 p
= buildtree(MUL
, p
, bcon(off
/SZCHAR
));
230 p
= buildtree(PLUS
, p
, bcon(3));
231 p
= buildtree(RS
, p
, bcon(2));
235 /* save the address of sp */
236 sp
= block(REG
, NIL
, NIL
, PTR
+INT
, t
->n_df
, t
->n_sue
);
239 t
->n_type
= sp
->n_type
;
240 ecomp(buildtree(ASSIGN
, t
, sp
)); /* Emit! */
242 /* add the size to sp */
243 sp
= block(REG
, NIL
, NIL
, p
->n_type
, 0, 0);
246 ecomp(buildtree(PLUSEQ
, sp
, p
));
250 * print out a constant node
251 * mat be associated with a label
262 t
= INT
; /* pointer */
267 inval(p
->n_lval
& 0xffffffff);
268 inval(p
->n_lval
>> 32);
274 printf("\t.long 0x%x", (int)p
->n_lval
);
275 if ((q
= p
->n_sp
) != NULL
) {
276 if ((q
->sclass
== STATIC
&& q
->slevel
> 0)) {
277 printf("+" LABFMT
, q
->soffset
);
279 printf("+%s", exname(q
->soname
));
290 * print out an integer.
296 printf(" .long 0x%llx\n", word
);
299 /* output code to initialize a floating point value */
300 /* the proper alignment has been obtained */
306 printf("\t.tfloat\t0t%.20Le\n", p
->n_dcon
);
309 printf("\t.dfloat\t0d%.20e\n", (double)p
->n_dcon
);
312 printf("\t.ffloat\t0f%.20e\n", (float)p
->n_dcon
);
317 /* make a name look like an external name in the local machine */
327 * map types which are not defined on the local machine
332 switch (BTYPE(type
)) {
338 MODTYPE(type
,UNSIGNED
);
350 MODTYPE(type
,DOUBLE
);
356 /* curid is a variable which is defined but
357 * is not initialized (and not a function );
358 * This routine returns the storage class for an uninitialized declaration
367 * Extern variable not necessary common.
370 extdec(struct symtab
*q
)
372 extern void addsym(struct symtab
*);
380 calldec(NODE
*p
, NODE
*r
)
382 struct symtab
*q
= p
->n_sp
;
383 extern void addsym(struct symtab
*);
387 /* make a common declaration for id, if reasonable */
389 commdec(struct symtab
*q
)
394 off
= tsize(q
->stype
, q
->sdf
, q
->ssue
);
395 off
= (off
+(SZCHAR
-1))/SZCHAR
;
397 printf(" PUBLIC %s\n", c
);
398 /* XXX - NOROOT??? */
399 printf(" RSEG DATA16_Z:NEARDATA:SORT:NOROOT(1)\n");
401 printf(" DS8 %d\n", off
);
402 printf(" REQUIRE __data16_zero\n");
405 /* make a local common declaration for id, if reasonable */
407 lcommdec(struct symtab
*q
)
411 off
= tsize(q
->stype
, q
->sdf
, q
->ssue
);
412 off
= (off
+(SZCHAR
-1))/SZCHAR
;
414 printf(" .lcomm %s,0%o\n", exname(q
->soname
), off
);
416 printf(" .lcomm " LABFMT
",0%o\n", q
->soffset
, off
);
420 * print a (non-prog) label.
425 printf(LABFMT
":\n", label
);
437 * special handling before tree is written out.
451 if (p
->n_type
== LONG
|| p
->n_type
== ULONG
) {
452 /* Swap arguments for hardops() later */
454 p
->n_left
= p
->n_right
;
462 * inform pass2 about varargs.
463 * store first variadic argument number in n_stalign
466 if (p
->n_right
->n_op
!= CM
)
467 break; /* nothing to care about */
468 df
= p
->n_left
->n_df
;
469 if (df
&& (al
= df
->dfun
)) {
470 for (i
= 0; i
< 6; i
++, al
++) {
471 if (al
->type
== TELLIPSIS
|| al
->type
== TNULL
)
474 p
->n_right
->n_stalign
= al
->type
== TELLIPSIS
? i
: 0;
476 p
->n_right
->n_stalign
= 0;
480 /* Write float constants to memory */
481 sp
= inlalloc(sizeof(struct symtab
));
483 sp
->ssue
= MKSUE(p
->n_type
);
484 sp
->slevel
= 1; /* fake numeric label */
485 sp
->soffset
= getlab();
487 sp
->stype
= p
->n_type
;
488 sp
->squal
= (CON
>> TSHIFT
);
491 ninval(0, sp
->ssue
->suesize
, p
);
501 * Give target the opportunity of handling pragmas.
509 * Called when a identifier has been declared, to give target last word.
512 fixdef(struct symtab
*sp
)
517 pass1_lastchance(struct interpass
*ip
)