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
58static 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 old 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
158ExitPoint:
159 /* The expression has always the new type */
160 ReplaceType (Expr, NewType);
161}
162
163
164
165void 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 at '%s'", (Expr->Sym? Expr->Sym->Name : "Unknown"));
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
275void 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