]> git.sur5r.net Git - cc65/blob - src/cc65/typecast.c
Work on better type casts - not yet finished
[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 and use the new one */
82     OldType = lval->Type;
83     lval->Type = TypeDup (NewType);
84
85     /* If we're casting to void, we're done. Note: This does also cover a cast
86      * void -> void.
87      */
88     if (IsTypeVoid (NewType)) {
89         return 0;       /* Never an lvalue */
90     }
91
92     /* Don't allow casts from void to something else. The new type is already
93      * set which should avoid more errors, but code will not get generated
94      * because of the error.
95      */
96     if (IsTypeVoid (OldType)) {
97         Error ("Cannot cast from `void' to something else");
98         return k;
99     }
100
101     /* Get the sizes of the types. Since we've excluded void types, checking
102      * for known sizes makes sense here.
103      */
104     OldSize = CheckedSizeOf (OldType);
105     NewSize = CheckedSizeOf (NewType);
106
107     /* Is this a cast of something into an integer? */
108     if (IsClassInt (NewType)) {
109
110         /* lvalue? */
111         if (k != 0) {
112
113             /* We have an lvalue. If the new size is smaller than the new one,
114              * we don't need to do anything. The compiler will generate code
115              * to load only the portion of the value that is actually needed.
116              * This works only on a little endian architecture, but that's
117              * what we support.
118              * If both sizes are equal, do also leave the value alone.
119              * If the new size is larger, we must convert the value.
120              */
121             if (NewSize > OldSize) {
122                 /* Load the value into the primary */
123                 exprhs (CF_NONE, k, lval);
124
125                 /* Emit typecast code */
126                 g_typecast (TypeOf (OldType), TypeOf (NewType));
127
128                 /* Value is now in primary */
129                 lval->Flags = E_MEXPR;
130                 k = 0;
131             }
132
133         } else {
134
135             /* We have an rvalue. Check for a constant. */
136             if (lval->Flags == E_MCONST) {
137
138                 /* A cast of a constant to an integer. Be sure to handle sign
139                  * extension correctly.
140                  */
141
142                 /* Get the current and new size of the value */
143                 unsigned OldBits = OldSize * 8;
144                 unsigned NewBits = NewSize * 8;
145
146                 /* Check if the new datatype will have a smaller range */
147                 if (NewBits <= OldBits) {
148
149                     /* Cut the value to the new size */
150                     lval->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
151
152                     /* If the new type is signed, sign extend the value */
153                     if (!IsSignUnsigned (NewType)) {
154                         lval->ConstVal |= ((~0L) << NewBits);
155                     }
156
157                 } else {
158
159                     /* Sign extend the value if needed */
160                     if (!IsSignUnsigned (OldType) && !IsSignUnsigned (NewType)) {
161                         if (lval->ConstVal & (0x01UL << (OldBits-1))) {
162                             lval->ConstVal |= ((~0L) << OldBits);
163                         }
164                     }
165                 }
166
167             } else {
168
169                 /* The value is not a constant. If the sizes of the types are
170                  * not equal, add conversion code. Be sure to convert chars
171                  * correctly.
172                  */
173                 if (OldSize != NewSize) {
174
175                     /* Load the value into the primary */
176                     exprhs (CF_NONE, k, lval);
177
178                     /* Emit typecast code. ### CHARS */
179                     g_typecast (TypeOf (OldType), TypeOf (NewType));
180
181                     /* Value is now in primary */
182                     lval->Flags = E_MEXPR;
183                     k = 0;
184                 }
185             }
186         }
187
188     } else {
189
190         /* All other stuff is handled equally */
191         if (NewSize != OldSize) {
192             /* Load the value into the primary */
193             exprhs (CF_NONE, k, lval);
194
195             /* Emit typecast code */
196             g_typecast (TypeOf (OldType), TypeOf (NewType));
197
198             /* Value is now in primary */
199             lval->Flags = E_MEXPR;
200             k = 0;
201         }
202     }
203
204     /* Done */
205     return k;
206 }
207
208
209
210
211
212