1 /*****************************************************************************/
5 /* Handle type casts */
9 /* (C) 2002 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
47 /*****************************************************************************/
49 /*****************************************************************************/
53 int TypeCast (ExprDesc* lval)
54 /* Handle an explicit cast. The function returns true if the resulting
55 * expression is an lvalue and false if not.
60 type NewType[MAXTYPELEN];
64 /* Skip the left paren */
73 /* Read the expression we have to cast */
76 /* If the expression is a function, treat it as pointer-to-function */
77 if (IsTypeFunc (lval->Type)) {
78 lval->Type = PointerTo (lval->Type);
81 /* Remember the old type */
84 /* If we're casting to void, we're done. Note: This does also cover a cast
87 if (IsTypeVoid (NewType)) {
88 k = 0; /* Never an lvalue */
92 /* Don't allow casts from void to something else. */
93 if (IsTypeVoid (OldType)) {
94 Error ("Cannot cast from `void' to something else");
98 /* Get the sizes of the types. Since we've excluded void types, checking
99 * for known sizes makes sense here.
101 OldSize = CheckedSizeOf (OldType);
102 NewSize = CheckedSizeOf (NewType);
104 /* Is this a cast of something into an integer? */
105 if (IsClassInt (NewType)) {
110 /* We have an lvalue. If the new size is smaller than the new one,
111 * we don't need to do anything. The compiler will generate code
112 * to load only the portion of the value that is actually needed.
113 * This works only on a little endian architecture, but that's
115 * If both sizes are equal, do also leave the value alone.
116 * If the new size is larger, we must convert the value.
118 if (NewSize > OldSize) {
119 /* Load the value into the primary */
120 exprhs (CF_NONE, k, lval);
122 /* Emit typecast code */
123 g_typecast (TypeOf (OldType), TypeOf (NewType));
125 /* Value is now in primary */
126 lval->Flags = E_MEXPR;
132 /* We have an rvalue. Check for a constant. */
133 if (lval->Flags == E_MCONST) {
135 /* A cast of a constant to an integer. Be sure to handle sign
136 * extension correctly.
139 /* Get the current and new size of the value */
140 unsigned OldBits = OldSize * 8;
141 unsigned NewBits = NewSize * 8;
143 /* Check if the new datatype will have a smaller range */
144 if (NewBits <= OldBits) {
146 /* Cut the value to the new size */
147 lval->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
149 /* If the new type is signed, sign extend the value */
150 if (!IsSignUnsigned (NewType)) {
151 lval->ConstVal |= ((~0L) << NewBits);
156 /* Sign extend the value if needed */
157 if (!IsSignUnsigned (OldType) && !IsSignUnsigned (NewType)) {
158 if (lval->ConstVal & (0x01UL << (OldBits-1))) {
159 lval->ConstVal |= ((~0L) << OldBits);
166 /* The value is not a constant. If the sizes of the types are
167 * not equal, add conversion code. Be sure to convert chars
170 if (OldSize != NewSize) {
172 /* Load the value into the primary */
173 exprhs (CF_NONE, k, lval);
175 /* Emit typecast code. */
176 g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
178 /* Value is now in primary */
179 lval->Flags = E_MEXPR;
187 /* All other stuff is handled equally */
188 if (NewSize != OldSize) {
189 /* Load the value into the primary */
190 exprhs (CF_NONE, k, lval);
192 /* Emit typecast code */
193 g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
195 /* Value is now in primary */
196 lval->Flags = E_MEXPR;
202 /* The expression has always the new type */
203 ReplaceType (lval, NewType);