1 /* $Id: local.c,v 1.8 2011/01/21 21:47: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 */
41 switch( o
= p
->n_op
){
43 /* handle variables */
44 if ((q
= p
->n_sp
) == NULL
)
45 return p
; /* Nothing to care about */
48 /* fake up a structure reference */
49 r
= block(REG
, NIL
, NIL
, PTR
+STRTY
, 0, 0);
52 p
= stref(block(STREF
, r
, p
, 0, 0, 0));
61 if( p
->n_right
->n_op
!= ICON
) cerror( "bad conversion", 0);
63 return(buildtree(o
==PMCONV
?MUL
:DIV
, p
->n_left
, p
->n_right
));
67 /* if conversion to another pointer type, just remove */
68 if (p
->n_type
> BTMASK
&& l
->n_type
> BTMASK
)
72 delp
: l
->n_type
= p
->n_type
;
73 l
->n_qual
= p
->n_qual
;
82 register struct symtab
*q
;
89 //fwalk(p, eprint, 0);
90 switch( o
= p
->n_op
){
93 if ((q
= p
->n_sp
) == NULL
)
94 return p
; /* Nothing to care about */
100 /* fake up a structure reference */
101 r
= block(REG
, NIL
, NIL
, PTR
+STRTY
, 0, 0);
104 p
= stref(block(STREF
, r
, p
, 0, 0, 0));
117 p
->n_rval
= q
->soffset
;
125 /* Fix function call arguments. On x86, just add funarg */
126 for (r
= p
->n_right
; r
->n_op
== CM
; r
= r
->n_left
) {
127 if (r
->n_right
->n_op
!= STARG
&&
128 r
->n_right
->n_op
!= FUNARG
)
129 r
->n_right
= block(FUNARG
, r
->n_right
, NIL
,
130 r
->n_right
->n_type
, r
->n_right
->n_df
,
133 if (r
->n_op
!= STARG
&& r
->n_op
!= FUNARG
) {
136 r
->n_op
= FUNARG
; r
->n_left
= l
; r
->n_type
= l
->n_type
;
144 * Remove unnecessary conversion ops.
146 if (clogop(l
->n_op
) && l
->n_left
->n_op
== SCONV
) {
147 if (coptype(l
->n_op
) != BITYPE
)
149 if (l
->n_right
->n_op
== ICON
) {
150 r
= l
->n_left
->n_left
;
151 if (r
->n_type
>= FLOAT
&& r
->n_type
<= LDOUBLE
)
153 /* Type must be correct */
158 l
->n_right
->n_type
= t
;
164 /* Remove redundant PCONV's. Be careful */
166 if (l
->n_op
== ICON
) {
167 l
->n_lval
= (unsigned)l
->n_lval
;
170 if (l
->n_type
< INT
|| l
->n_type
== LONGLONG
||
171 l
->n_type
== ULONGLONG
) {
173 p
->n_left
= block(SCONV
, l
, NIL
,
174 UNSIGNED
, 0, MKSUE(UNSIGNED
));
177 /* if left is SCONV, cannot remove */
178 if (l
->n_op
== SCONV
)
180 /* if conversion to another pointer type, just remove */
181 if (p
->n_type
> BTMASK
&& l
->n_type
> BTMASK
)
185 delp
: l
->n_type
= p
->n_type
;
186 l
->n_qual
= p
->n_qual
;
196 if (p
->n_type
== l
->n_type
) {
201 if ((p
->n_type
& TMASK
) == 0 && (l
->n_type
& TMASK
) == 0 &&
202 btdims
[p
->n_type
].suesize
== btdims
[l
->n_type
].suesize
) {
203 if (p
->n_type
!= FLOAT
&& p
->n_type
!= DOUBLE
&&
204 l
->n_type
!= FLOAT
&& l
->n_type
!= DOUBLE
&&
205 l
->n_type
!= LDOUBLE
&& p
->n_type
!= LDOUBLE
) {
206 if (l
->n_op
== NAME
|| l
->n_op
== UMUL
||
208 l
->n_type
= p
->n_type
;
215 if (DEUNSIGN(p
->n_type
) == INT
&& DEUNSIGN(l
->n_type
) == INT
&&
216 coptype(l
->n_op
) == BITYPE
) {
217 l
->n_type
= p
->n_type
;
226 CONSZ val
= l
->n_lval
;
228 if (!ISPTR(m
)) /* Pointers don't need to be conv'd */
231 l
->n_lval
= (char)val
;
234 l
->n_lval
= val
& 0377;
237 l
->n_lval
= (short)val
;
240 l
->n_lval
= val
& 0177777;
244 l
->n_lval
= val
& 0xffffffff;
248 l
->n_lval
= (int)val
;
251 l
->n_lval
= (long long)val
;
265 cerror("unknown type %d", m
);
272 if (DEUNSIGN(p
->n_type
) == SHORT
&&
273 DEUNSIGN(l
->n_type
) == SHORT
) {
277 if ((p
->n_type
== CHAR
|| p
->n_type
== UCHAR
||
278 p
->n_type
== SHORT
|| p
->n_type
== USHORT
) &&
279 (l
->n_type
== FLOAT
|| l
->n_type
== DOUBLE
||
280 l
->n_type
== LDOUBLE
)) {
281 p
= block(SCONV
, p
, NIL
, p
->n_type
, p
->n_df
, p
->n_sue
);
282 p
->n_left
->n_type
= INT
;
289 if (o
== DIV
&& p
->n_type
!= CHAR
&& p
->n_type
!= SHORT
)
291 if (o
== MOD
&& p
->n_type
!= CHAR
&& p
->n_type
!= SHORT
)
293 /* make it an int division by inserting conversions */
294 p
->n_left
= block(SCONV
, p
->n_left
, NIL
, INT
, 0, MKSUE(INT
));
295 p
->n_right
= block(SCONV
, p
->n_right
, NIL
, INT
, 0, MKSUE(INT
));
296 p
= block(SCONV
, p
, NIL
, p
->n_type
, 0, MKSUE(p
->n_type
));
297 p
->n_left
->n_type
= INT
;
302 if( p
->n_right
->n_op
!= ICON
) cerror( "bad conversion", 0);
304 return(buildtree(o
==PMCONV
?MUL
:DIV
, p
->n_left
, p
->n_right
));
307 /* put return value in return reg */
309 p
->n_right
= p
->n_left
;
310 p
->n_left
= block(REG
, NIL
, NIL
, p
->n_type
, 0, MKSUE(INT
));
311 p
->n_left
->n_rval
= RETREG(p
->n_type
);
316 /* shift count must be in a char
317 * unless longlong, where it must be int */
318 if (p
->n_right
->n_op
== ICON
)
319 break; /* do not do anything */
320 if (p
->n_type
== LONGLONG
|| p
->n_type
== ULONGLONG
) {
321 if (p
->n_right
->n_type
!= INT
)
322 p
->n_right
= block(SCONV
, p
->n_right
, NIL
,
326 if (p
->n_right
->n_type
== CHAR
|| p
->n_right
->n_type
== UCHAR
)
328 p
->n_right
= block(SCONV
, p
->n_right
, NIL
,
329 CHAR
, 0, MKSUE(CHAR
));
333 //fwalk(p, eprint, 0);
349 sp
= inlalloc(sizeof(struct symtab
));
351 sp
->ssue
= MKSUE(p
->n_type
);
352 sp
->slevel
= 1; /* fake numeric label */
353 sp
->soffset
= getlab();
355 sp
->stype
= p
->n_type
;
356 sp
->squal
= (CON
>> TSHIFT
);
359 ninval(0, sp
->ssue
->suesize
, p
);
371 return(1); /* all names can have & taken on them */
375 * at the end of the arguments of a ftn, set the automatic offset
384 * Return 1 if a variable of type type is OK to put in register.
389 return 1; /* try to put anything in a register */
393 * return a node, for structure references, which is suitable for
394 * being added to a pointer of type t, in order to be off bits offset
396 * t, d, and s are the type, dimension offset, and sizeoffset
397 * For nova, return the type-specific index number which calculation
398 * is based on its size. For example, char a[3] would return 3.
399 * Be careful about only handling first-level pointers, the following
400 * indirections must be fullword.
403 offcon(OFFSZ off
, TWORD t
, union dimfun
*d
, struct suedef
*sue
)
408 printf("offcon: OFFSZ %ld type %x dim %p siz %d\n",
409 off
, t
, d
, sue
->suesize
);
412 p
->n_lval
= off
/SZINT
; /* Default */
413 if (ISPTR(DECREF(t
)))
415 if (t
== VOID
|| t
== CHAR
|| t
== UCHAR
)
416 p
->n_lval
= off
/SZCHAR
; /* pointer to char */
421 * Allocate off bits on the stack. p is a tree that when evaluated
422 * is the multiply count for off, t is a NAME node where to write
423 * the allocated address.
426 spalloc(NODE
*t
, NODE
*p
, OFFSZ off
)
431 if ((off
% SZINT
) == 0)
432 p
= buildtree(MUL
, p
, bcon(off
/SZINT
));
433 else if ((off
% SZSHORT
) == 0) {
434 p
= buildtree(MUL
, p
, bcon(off
/SZSHORT
));
435 p
= buildtree(PLUS
, p
, bcon(1));
436 p
= buildtree(RS
, p
, bcon(1));
437 } else if ((off
% SZCHAR
) == 0) {
438 p
= buildtree(MUL
, p
, bcon(off
/SZCHAR
));
439 p
= buildtree(PLUS
, p
, bcon(3));
440 p
= buildtree(RS
, p
, bcon(2));
444 /* save the address of sp */
445 sp
= block(REG
, NIL
, NIL
, PTR
+INT
, t
->n_df
, t
->n_sue
);
448 t
->n_type
= sp
->n_type
;
449 ecomp(buildtree(ASSIGN
, t
, sp
)); /* Emit! */
451 /* add the size to sp */
452 sp
= block(REG
, NIL
, NIL
, p
->n_type
, 0, 0);
455 ecomp(buildtree(PLUSEQ
, sp
, p
));
459 * print out a constant node
460 * mat be associated with a label
471 t
= INT
; /* pointer */
474 cerror("ninval: init node not constant");
479 inval(p
->n_lval
& 0xffff);
480 inval(p
->n_lval
>> 16);
484 printf("\t.word 0%o", (short)p
->n_lval
);
485 if ((q
= p
->n_sp
) != NULL
) {
486 if ((q
->sclass
== STATIC
&& q
->slevel
> 0)) {
487 printf("+" LABFMT
, q
->soffset
);
489 printf("+%s", exname(q
->soname
));
499 * print out an integer.
505 printf(" .word 0%o\n", (int)word
);
508 /* output code to initialize a floating point value */
509 /* the proper alignment has been obtained */
513 union { float f
; double d
; long double l
; int i
[3]; } u
;
519 u
.l
= (long double)p
->n_dcon
;
520 printf("\t.long\t0x%x,0x%x,0x%x\n", u
.i
[0], u
.i
[1], u
.i
[2]);
523 u
.d
= (double)p
->n_dcon
;
524 printf("\t.long\t0x%x,0x%x\n", u
.i
[0], u
.i
[1]);
527 u
.f
= (float)p
->n_dcon
;
528 printf("\t.long\t0x%x\n", u
.i
[0]);
533 /* make a name look like an external name in the local machine */
543 * map types which are not defined on the local machine
548 switch (BTYPE(type
)) {
560 MODTYPE(type
,UNSIGNED
);
566 /* curid is a variable which is defined but
567 * is not initialized (and not a function );
568 * This routine returns the storage class for an uninitialized declaration
577 calldec(NODE
*p
, NODE
*q
)
582 extdec(struct symtab
*q
)
586 /* make a common declaration for id, if reasonable */
588 commdec(struct symtab
*q
)
592 off
= tsize(q
->stype
, q
->sdf
, q
->ssue
);
593 off
= (off
+(SZCHAR
-1))/SZCHAR
;
594 printf(" .comm %s,0%o\n", exname(q
->soname
), off
);
597 /* make a local common declaration for id, if reasonable */
599 lcommdec(struct symtab
*q
)
603 off
= tsize(q
->stype
, q
->sdf
, q
->ssue
);
604 off
= (off
+(SZCHAR
-1))/SZCHAR
;
606 printf(" .lcomm %s,0%o\n", exname(q
->soname
), off
);
608 printf(" .lcomm " LABFMT
",0%o\n", q
->soffset
, off
);
612 * print a (non-prog) label.
617 printf(LABFMT
":\n", label
);
620 static char *loctbl
[] = { "text", "data", "section .rodata", "section .rodata" };
628 printf(" .%s\n", loctbl
[locc
]);
631 * Give target the opportunity of handling pragmas.
640 * Called when a identifier has been declared, to give target last word.
643 fixdef(struct symtab
*sp
)
648 pass1_lastchance(struct interpass
*ip
)