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