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 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 | |
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 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 | |
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 | |