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 and use the new one */
83 lval->Type = TypeDup (NewType);
85 /* If we're casting to void, we're done. Note: This does also cover a cast
88 if (IsTypeVoid (NewType)) {
89 return 0; /* Never an lvalue */
92 /* Don't allow casts from void to something else. The new type is already
93 * set which should avoid more errors, but code will not get generated
94 * because of the error.
96 if (IsTypeVoid (OldType)) {
97 Error ("Cannot cast from `void' to something else");
101 /* Get the sizes of the types. Since we've excluded void types, checking
102 * for known sizes makes sense here.
104 OldSize = CheckedSizeOf (OldType);
105 NewSize = CheckedSizeOf (NewType);
107 /* Is this a cast of something into an integer? */
108 if (IsClassInt (NewType)) {
113 /* We have an lvalue. If the new size is smaller than the new one,
114 * we don't need to do anything. The compiler will generate code
115 * to load only the portion of the value that is actually needed.
116 * This works only on a little endian architecture, but that's
118 * If both sizes are equal, do also leave the value alone.
119 * If the new size is larger, we must convert the value.
121 if (NewSize > OldSize) {
122 /* Load the value into the primary */
123 exprhs (CF_NONE, k, lval);
125 /* Emit typecast code */
126 g_typecast (TypeOf (OldType), TypeOf (NewType));
128 /* Value is now in primary */
129 lval->Flags = E_MEXPR;
135 /* We have an rvalue. Check for a constant. */
136 if (lval->Flags == E_MCONST) {
138 /* A cast of a constant to an integer. Be sure to handle sign
139 * extension correctly.
142 /* Get the current and new size of the value */
143 unsigned OldBits = OldSize * 8;
144 unsigned NewBits = NewSize * 8;
146 /* Check if the new datatype will have a smaller range */
147 if (NewBits <= OldBits) {
149 /* Cut the value to the new size */
150 lval->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
152 /* If the new type is signed, sign extend the value */
153 if (!IsSignUnsigned (NewType)) {
154 lval->ConstVal |= ((~0L) << NewBits);
159 /* Sign extend the value if needed */
160 if (!IsSignUnsigned (OldType) && !IsSignUnsigned (NewType)) {
161 if (lval->ConstVal & (0x01UL << (OldBits-1))) {
162 lval->ConstVal |= ((~0L) << OldBits);
169 /* The value is not a constant. If the sizes of the types are
170 * not equal, add conversion code. Be sure to convert chars
173 if (OldSize != NewSize) {
175 /* Load the value into the primary */
176 exprhs (CF_NONE, k, lval);
178 /* Emit typecast code. ### CHARS */
179 g_typecast (TypeOf (OldType), TypeOf (NewType));
181 /* Value is now in primary */
182 lval->Flags = E_MEXPR;
190 /* All other stuff is handled equally */
191 if (NewSize != OldSize) {
192 /* Load the value into the primary */
193 exprhs (CF_NONE, k, lval);
195 /* Emit typecast code */
196 g_typecast (TypeOf (OldType), TypeOf (NewType));
198 /* Value is now in primary */
199 lval->Flags = E_MEXPR;