]> git.sur5r.net Git - cc65/blob - src/cc65/typecast.c
The input file on the command line is optional
[cc65] / src / cc65 / typecast.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                typecast.c                                 */
4 /*                                                                           */
5 /*                             Handle type casts                             */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002      Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 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 /* cc65 */
37 #include "codegen.h"
38 #include "datatype.h"
39 #include "declare.h"
40 #include "error.h"
41 #include "expr.h"
42 #include "scanner.h"
43 #include "typecast.h"
44
45
46
47 /*****************************************************************************/
48 /*                                   Code                                    */
49 /*****************************************************************************/
50
51
52
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.
56  */
57 {
58     int      k;
59     type*    OldType;
60     type     NewType[MAXTYPELEN];
61     unsigned OldSize;
62     unsigned NewSize;
63
64     /* Skip the left paren */
65     NextToken ();
66
67     /* Read the type */
68     ParseType (NewType);
69
70     /* Closing paren */
71     ConsumeRParen ();
72
73     /* Read the expression we have to cast */
74     k = hie10 (lval);
75
76     /* If the expression is a function, treat it as pointer to function.
77      * If the expression is an array, treat it as pointer to first element.
78      */
79     if (IsTypeFunc (lval->Type)) {
80         lval->Type = PointerTo (lval->Type);
81     } else if (IsTypeArray (lval->Type)) {
82         lval->Type = ArrayToPtr (lval->Type);
83     }
84
85     /* Remember the old type */
86     OldType = lval->Type;
87
88     /* If we're casting to void, we're done. Note: This does also cover a cast
89      * void -> void.
90      */
91     if (IsTypeVoid (NewType)) {
92         k = 0;          /* Never an lvalue */
93         goto ExitPoint;
94     }
95
96     /* Don't allow casts from void to something else. */
97     if (IsTypeVoid (OldType)) {
98         Error ("Cannot cast from `void' to something else");
99         goto ExitPoint;
100     }
101
102     /* Get the sizes of the types. Since we've excluded void types, checking
103      * for known sizes makes sense here.
104      */
105     OldSize = CheckedSizeOf (OldType);
106     NewSize = CheckedSizeOf (NewType);
107
108     /* Is this a cast of something into an integer? */
109     if (IsClassInt (NewType)) {
110
111         /* lvalue? */
112         if (k != 0) {
113
114             /* We have an lvalue. If the new size is smaller than the new one,
115              * we don't need to do anything. The compiler will generate code
116              * to load only the portion of the value that is actually needed.
117              * This works only on a little endian architecture, but that's
118              * what we support.
119              * If both sizes are equal, do also leave the value alone.
120              * If the new size is larger, we must convert the value.
121              */
122             if (NewSize > OldSize) {
123                 /* Load the value into the primary */
124                 exprhs (CF_NONE, k, lval);
125
126                 /* Emit typecast code */
127                 g_typecast (TypeOf (OldType), TypeOf (NewType));
128
129                 /* Value is now in primary */
130                 lval->Flags = E_MEXPR;
131                 k = 0;
132             }
133
134         } else {
135
136             /* We have an rvalue. Check for a constant. */
137             if (lval->Flags == E_MCONST) {
138
139                 /* A cast of a constant to an integer. Be sure to handle sign
140                  * extension correctly.
141                  */
142
143                 /* Get the current and new size of the value */
144                 unsigned OldBits = OldSize * 8;
145                 unsigned NewBits = NewSize * 8;
146
147                 /* Check if the new datatype will have a smaller range. If it
148                  * has a larger range, things are ok, since the value is 
149                  * internally already represented by a long.
150                  */
151                 if (NewBits <= OldBits) {
152
153                     /* Cut the value to the new size */
154                     lval->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
155
156                     /* If the new type is signed, sign extend the value */
157                     if (!IsSignUnsigned (NewType)) {
158                         if (lval->ConstVal & (0x01UL << (NewBits-1))) {
159                             lval->ConstVal |= ((~0L) << NewBits);
160                         }
161                     }
162                 }
163
164             } else {
165
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
168                  * correctly.
169                  */
170                 if (OldSize != NewSize) {
171
172                     /* Load the value into the primary */
173                     exprhs (CF_NONE, k, lval);
174
175                     /* Emit typecast code. */
176                     g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
177
178                     /* Value is now in primary */
179                     lval->Flags = E_MEXPR;
180                     k = 0;
181                 }
182             }
183         }
184
185     } else {
186
187         /* All other stuff is handled equally */
188         if (NewSize != OldSize) {
189             /* Load the value into the primary */
190             exprhs (CF_NONE, k, lval);
191
192             /* Emit typecast code */
193             g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
194
195             /* Value is now in primary */
196             lval->Flags = E_MEXPR;
197             k = 0;
198         }
199     }
200
201 ExitPoint:
202     /* The expression has always the new type */
203     ReplaceType (lval, NewType);
204
205     /* Done */
206     return k;
207 }
208
209
210
211
212
213