]> git.sur5r.net Git - cc65/blob - src/cc65/typeconv.c
Renamed exprhs to ExprLoad
[cc65] / src / cc65 / typeconv.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                typeconv.c                                 */
4 /*                                                                           */
5 /*                          Handle type conversions                          */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 52                                             */
11 /*               D-70794 Filderstadt                                         */
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 "typecmp.h"
44 #include "typeconv.h"
45
46
47
48 /*****************************************************************************/
49 /*                                   Code                                    */
50 /*****************************************************************************/
51
52
53
54 static void DoPtrConversions (ExprDesc* Expr)
55 /* If the expression is a function, convert it to pointer to function.
56  * If the expression is an array, convert it to pointer to first element.
57  */
58 {
59     if (IsTypeFunc (Expr->Type)) {
60         Expr->Type = PointerTo (Expr->Type);
61     } else if (IsTypeArray (Expr->Type)) {
62         Expr->Type = ArrayToPtr (Expr->Type);
63     }
64 }
65
66
67
68 static int DoConversion (ExprDesc* Expr, int k, type* NewType)
69 /* Emit code to convert the given expression to a new type. */
70 {
71     type*    OldType;
72     unsigned OldSize;
73     unsigned NewSize;
74
75
76     /* Remember the old type */
77     OldType = Expr->Type;
78
79     /* If we're converting to void, we're done. Note: This does also cover a
80      * conversion void -> void.
81      */
82     if (IsTypeVoid (NewType)) {
83         k = 0;          /* Never an lvalue */
84         goto ExitPoint;
85     }
86
87     /* Don't allow casts from void to something else. */
88     if (IsTypeVoid (OldType)) {
89         Error ("Cannot convert from `void' to something else");
90         goto ExitPoint;
91     }
92
93     /* Get the sizes of the types. Since we've excluded void types, checking
94      * for known sizes makes sense here.
95      */
96     OldSize = CheckedSizeOf (OldType);
97     NewSize = CheckedSizeOf (NewType);
98
99     /* lvalue? */
100     if (k != 0) {
101
102         /* We have an lvalue. If the new size is smaller than the new one,
103          * we don't need to do anything. The compiler will generate code
104          * to load only the portion of the value that is actually needed.
105          * This works only on a little endian architecture, but that's
106          * what we support.
107          * If both sizes are equal, do also leave the value alone.
108          * If the new size is larger, we must convert the value.
109          */
110         if (NewSize > OldSize) {
111             /* Load the value into the primary */
112             ExprLoad (CF_NONE, k, Expr);
113
114             /* Emit typecast code */
115             g_typecast (TypeOf (NewType), TypeOf (OldType));
116
117             /* Value is now in primary */
118             Expr->Flags = E_MEXPR;
119             k = 0;
120         }
121
122     } else {
123
124         /* We have an rvalue. Check for a constant. */
125         if (Expr->Flags == E_MCONST) {
126
127             /* A cast of a constant to an integer. Be sure to handle sign
128              * extension correctly.
129              */
130
131             /* Get the current and new size of the value */
132             unsigned OldBits = OldSize * 8;
133             unsigned NewBits = NewSize * 8;
134
135             /* Check if the new datatype will have a smaller range. If it
136              * has a larger range, things are ok, since the value is
137              * internally already represented by a long.
138              */
139             if (NewBits <= OldBits) {
140
141                 /* Cut the value to the new size */
142                 Expr->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
143
144                 /* If the new type is signed, sign extend the value */
145                 if (!IsSignUnsigned (NewType)) {
146                     if (Expr->ConstVal & (0x01UL << (NewBits-1))) {
147                         Expr->ConstVal |= ((~0L) << NewBits);
148                     }
149                 }
150             }
151
152         } else {
153
154             /* The value is not a constant. If the sizes of the types are
155              * not equal, add conversion code. Be sure to convert chars
156              * correctly.
157              */
158             if (OldSize != NewSize) {
159
160                 /* Load the value into the primary */
161                 ExprLoad (CF_NONE, k, Expr);
162
163                 /* Emit typecast code. */
164                 g_typecast (TypeOf (NewType) | CF_FORCECHAR, TypeOf (OldType));
165
166                 /* Value is now in primary */
167                 Expr->Flags = E_MEXPR;
168                 k = 0;
169             }
170         }
171     }
172
173 ExitPoint:
174     /* The expression has always the new type */
175     ReplaceType (Expr, NewType);
176
177     /* Done */
178     return k;
179 }
180
181
182
183 int TypeConversion (ExprDesc* Expr, int k, type* NewType)
184 /* Do an automatic conversion of the given expression to the new type. Output
185  * warnings or errors where this automatic conversion is suspicious or
186  * impossible.
187  */
188 {
189     /* Get the type of the right hand side. Treat function types as
190      * pointer-to-function
191      */
192     DoPtrConversions (Expr);
193
194     /* First, do some type checking */
195     if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) {
196         /* If one of the sides are of type void, output a more apropriate
197          * error message.
198          */
199         Error ("Illegal type");
200         return k;
201     }
202
203     /* Handle conversions to int type */
204     if (IsClassInt (NewType)) {
205         if (IsClassPtr (Expr->Type)) {
206             /* Pointer -> int conversion */
207             Warning ("Converting pointer to integer without a cast");
208         } else if (!IsClassInt (Expr->Type)) {
209             Error ("Incompatible types");
210         }
211
212         /* Do a conversion regardless of errors and return the result. */
213         return DoConversion (Expr, k, NewType);
214     }
215
216     /* Handle conversions to pointer type */
217     if (IsClassPtr (NewType)) {
218         if (IsClassPtr (Expr->Type)) {
219             /* Pointer to pointer assignment is valid, if:
220              *   - both point to the same types, or
221              *   - the rhs pointer is a void pointer, or
222              *   - the lhs pointer is a void pointer.
223              */
224             if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) {
225                 /* Compare the types */
226                 switch (TypeCmp (NewType, Expr->Type)) {
227
228                     case TC_INCOMPATIBLE:
229                         Error ("Incompatible pointer types");
230                         break;
231
232                     case TC_QUAL_DIFF:
233                         Error ("Pointer types differ in type qualifiers");
234                         break;
235
236                     default:
237                         /* Ok */
238                         break;
239                 }
240             }
241         } else if (IsClassInt (Expr->Type)) {
242             /* Int to pointer assignment is valid only for constant zero */
243             if (Expr->Flags != E_MCONST || Expr->ConstVal != 0) {
244                 Warning ("Converting integer to pointer without a cast");
245             }
246         } else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) {
247             /* Assignment of function to function pointer is allowed, provided
248              * that both functions have the same parameter list.
249              */
250             if (TypeCmp (Indirect (NewType), Expr->Type) < TC_EQUAL) {
251                 Error ("Incompatible types");
252             }
253         } else {
254             Error ("Incompatible types");
255         }
256
257         /* Do the conversion even in case of errors */
258         return DoConversion (Expr, k, NewType);
259
260     }
261
262     /* Invalid automatic conversion */
263     Error ("Incompatible types");
264     return DoConversion (Expr, k, NewType);
265 }
266
267
268
269 int TypeCast (ExprDesc* Expr)
270 /* Handle an explicit cast. The function returns true if the resulting
271  * expression is an lvalue and false if not.
272  */
273 {
274     int     k;
275     type    NewType[MAXTYPELEN];
276
277     /* Skip the left paren */
278     NextToken ();
279
280     /* Read the type */
281     ParseType (NewType);
282
283     /* Closing paren */
284     ConsumeRParen ();
285
286     /* Read the expression we have to cast */
287     k = hie10 (Expr);
288
289     /* Convert functions and arrays to "pointer to" object */
290     DoPtrConversions (Expr);
291
292     /* Convert the value and return the result. */
293     return DoConversion (Expr, k, NewType);
294 }
295
296
297