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