]> git.sur5r.net Git - cc65/blob - src/cc65/typecast.c
Another optimization step
[cc65] / src / cc65 / typecast.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                typecast.c                                 */
4 /*                                                                           */
5 /*                             Handle type casts                             */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002      Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 /* cc65 */
37 #include "codegen.h"
38 #include "datatype.h"
39 #include "declare.h"
40 #include "error.h"
41 #include "expr.h"
42 #include "scanner.h"
43 #include "typecast.h"
44
45
46
47 /*****************************************************************************/
48 /*                                   Code                                    */
49 /*****************************************************************************/
50
51
52
53 int TypeCast (ExprDesc* lval)
54 /* Handle an explicit cast. The function returns true if the resulting
55  * expression is an lvalue and false if not.
56  */
57 {
58     int      k;
59     type*    OldType;
60     type     NewType[MAXTYPELEN];
61     unsigned OldSize;
62     unsigned NewSize;
63
64     /* Skip the left paren */
65     NextToken ();
66
67     /* Read the type */
68     ParseType (NewType);
69
70     /* Closing paren */
71     ConsumeRParen ();
72
73     /* Read the expression we have to cast */
74     k = hie10 (lval);
75
76     /* If the expression is a function, treat it as pointer-to-function */
77     if (IsTypeFunc (lval->Type)) {
78         lval->Type = PointerTo (lval->Type);
79     }
80
81     /* Remember the old type */
82     OldType = lval->Type;
83
84     /* If we're casting to void, we're done. Note: This does also cover a cast
85      * void -> void.
86      */
87     if (IsTypeVoid (NewType)) {
88         k = 0;          /* Never an lvalue */
89         goto ExitPoint;
90     }
91
92     /* Don't allow casts from void to something else. */
93     if (IsTypeVoid (OldType)) {
94         Error ("Cannot cast from `void' to something else");
95         goto ExitPoint;
96     }
97
98     /* Get the sizes of the types. Since we've excluded void types, checking
99      * for known sizes makes sense here.
100      */
101     OldSize = CheckedSizeOf (OldType);
102     NewSize = CheckedSizeOf (NewType);
103
104     /* Is this a cast of something into an integer? */
105     if (IsClassInt (NewType)) {
106
107         /* lvalue? */
108         if (k != 0) {
109
110             /* We have an lvalue. If the new size is smaller than the new one,
111              * we don't need to do anything. The compiler will generate code
112              * to load only the portion of the value that is actually needed.
113              * This works only on a little endian architecture, but that's
114              * what we support.
115              * If both sizes are equal, do also leave the value alone.
116              * If the new size is larger, we must convert the value.
117              */
118             if (NewSize > OldSize) {
119                 /* Load the value into the primary */
120                 exprhs (CF_NONE, k, lval);
121
122                 /* Emit typecast code */
123                 g_typecast (TypeOf (OldType), TypeOf (NewType));
124
125                 /* Value is now in primary */
126                 lval->Flags = E_MEXPR;
127                 k = 0;
128             }
129
130         } else {
131
132             /* We have an rvalue. Check for a constant. */
133             if (lval->Flags == E_MCONST) {
134
135                 /* A cast of a constant to an integer. Be sure to handle sign
136                  * extension correctly.
137                  */
138
139                 /* Get the current and new size of the value */
140                 unsigned OldBits = OldSize * 8;
141                 unsigned NewBits = NewSize * 8;
142
143                 /* Check if the new datatype will have a smaller range */
144                 if (NewBits <= OldBits) {
145
146                     /* Cut the value to the new size */
147                     lval->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
148
149                     /* If the new type is signed, sign extend the value */
150                     if (!IsSignUnsigned (NewType)) {
151                         lval->ConstVal |= ((~0L) << NewBits);
152                     }
153
154                 } else {
155
156                     /* Sign extend the value if needed */
157                     if (!IsSignUnsigned (OldType) && !IsSignUnsigned (NewType)) {
158                         if (lval->ConstVal & (0x01UL << (OldBits-1))) {
159                             lval->ConstVal |= ((~0L) << OldBits);
160                         }
161                     }
162                 }
163
164             } else {
165
166                 /* The value is not a constant. If the sizes of the types are
167                  * not equal, add conversion code. Be sure to convert chars
168                  * correctly.
169                  */
170                 if (OldSize != NewSize) {
171
172                     /* Load the value into the primary */
173                     exprhs (CF_NONE, k, lval);
174
175                     /* Emit typecast code. */
176                     g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
177
178                     /* Value is now in primary */
179                     lval->Flags = E_MEXPR;
180                     k = 0;
181                 }
182             }
183         }
184
185     } else {
186
187         /* All other stuff is handled equally */
188         if (NewSize != OldSize) {
189             /* Load the value into the primary */
190             exprhs (CF_NONE, k, lval);
191
192             /* Emit typecast code */
193             g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
194
195             /* Value is now in primary */
196             lval->Flags = E_MEXPR;
197             k = 0;
198         }
199     }
200
201 ExitPoint:
202     /* The expression has always the new type */
203     ReplaceType (lval, NewType);
204
205     /* Done */
206     return k;
207 }
208
209
210
211
212
213