]> git.sur5r.net Git - cc65/blob - src/cc65/typecmp.c
Handle intermediate access to local variables in the stack op optimizations.
[cc65] / src / cc65 / typecmp.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 typecmp.c                                 */
4 /*                                                                           */
5 /*               Type compare function for the cc65 C compiler               */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2000 Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
12 /* EMail:        uz@musoftware.de                                            */
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 #include "funcdesc.h"
37 #include "symtab.h"
38 #include "typecmp.h"
39
40
41
42 /*****************************************************************************/
43 /*                                   Code                                    */
44 /*****************************************************************************/
45
46
47
48 static void SetResult (typecmp_t* Result, typecmp_t Val)
49 /* Set a new result value if it is less than the existing one */
50 {
51     if (Val < *Result) {
52         *Result = Val;
53     }
54 }
55
56
57
58 static int EqualFuncParams (SymTable* Tab1, SymTable* Tab2)
59 /* Compare two function symbol tables regarding function parameters. Return 1
60  * if they are equal and 0 otherwise.
61  */
62 {
63     /* Compare the parameter lists */
64     SymEntry* Sym1 = Tab1->SymHead;
65     SymEntry* Sym2 = Tab2->SymHead;
66
67     /* Compare the fields */
68     while (Sym1 && (Sym1->Flags & SC_PARAM) && Sym2 && (Sym2->Flags & SC_PARAM)) {
69
70         /* Compare this field */
71         if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
72             /* Field types not equal */
73             return 0;
74         }
75
76         /* Get the pointers to the next fields */
77         Sym1 = Sym1->NextSym;
78         Sym2 = Sym2->NextSym;
79     }
80
81     /* Check both pointers against NULL or a non parameter to compare the 
82      * field count 
83      */
84     return (Sym1 == 0 || (Sym1->Flags & SC_PARAM) == 0) &&
85            (Sym2 == 0 || (Sym2->Flags & SC_PARAM) == 0);
86 }
87
88
89
90 static int EqualSymTables (SymTable* Tab1, SymTable* Tab2)
91 /* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */
92 {
93     /* Compare the parameter lists */
94     SymEntry* Sym1 = Tab1->SymHead;
95     SymEntry* Sym2 = Tab2->SymHead;
96
97     /* Compare the fields */
98     while (Sym1 && Sym2) {
99
100         /* Compare this field */
101         if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
102             /* Field types not equal */
103             return 0;
104         }
105
106         /* Get the pointers to the next fields */
107         Sym1 = Sym1->NextSym;
108         Sym2 = Sym2->NextSym;
109     }
110
111     /* Check both pointers against NULL to compare the field count */
112     return (Sym1 == 0 && Sym2 == 0);
113 }
114
115
116
117 static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result)
118 /* Recursively compare two types. */
119 {
120     unsigned    Indirections;
121     unsigned    ElementCount;
122     SymEntry*   Sym1;
123     SymEntry*   Sym2;
124     SymTable*   Tab1;
125     SymTable*   Tab2;
126     FuncDesc*   F1;
127     FuncDesc*   F2;
128     int         Ok;
129
130
131     /* Initialize stuff */
132     Indirections = 0;
133     ElementCount = 0;
134
135     /* Compare two types. Determine, where they differ */
136     while (*lhs != T_END) {
137
138         type LeftType, RightType;
139         type LeftSign, RightSign;
140         type LeftQual, RightQual;
141         unsigned LeftCount, RightCount;
142
143         /* Check if the end of the type string is reached */
144         if (*rhs == T_END) {
145             /* End of comparison reached */
146             return;
147         }
148
149         /* Get the raw left and right types, signs and qualifiers */
150         LeftType  = GetType (lhs);
151         RightType = GetType (rhs);
152         LeftSign  = GetSignedness (lhs);
153         RightSign = GetSignedness (rhs);
154         LeftQual  = GetQualifier (lhs);
155         RightQual = GetQualifier (rhs);
156
157         /* If the left type is a pointer and the right is an array, both
158          * are compatible.
159          */
160         if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
161             RightType = T_TYPE_PTR;
162             rhs += DECODE_SIZE;
163         }
164
165         /* If the raw types are not identical, the types are incompatible */
166         if (LeftType != RightType) {
167             SetResult (Result, TC_INCOMPATIBLE);
168             return;
169         }
170
171         /* On indirection level zero, a qualifier or sign difference is
172          * accepted. The types are no longer equal, but compatible.
173          */
174         if (LeftSign != RightSign) {
175             if (ElementCount == 0) {
176                 SetResult (Result, TC_SIGN_DIFF);
177             } else {
178                 SetResult (Result, TC_INCOMPATIBLE);
179                 return;
180             }
181         }
182         if (LeftQual != RightQual) {
183             /* On the first indirection level, different qualifiers mean
184              * that the types are still compatible. On the second level,
185              * this is a (maybe minor) error, so we create a special
186              * return code, since a qualifier is dropped from a pointer.
187              * Starting from the next level, the types are incompatible
188              * if the qualifiers differ.
189              */
190             switch (Indirections) {
191
192                 case 0:
193                     SetResult (Result, TC_STRICT_COMPATIBLE);
194                     break;
195
196                 case 1:
197                     /* A non const value on the right is compatible to a
198                      * const one to the left, same for volatile.
199                      */
200                     if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) ||
201                         (LeftQual & T_QUAL_VOLATILE) < (RightQual & T_QUAL_VOLATILE)) {
202                         SetResult (Result, TC_QUAL_DIFF);
203                     } else {
204                         SetResult (Result, TC_STRICT_COMPATIBLE);
205                     }
206                     break;
207
208                 default:
209                     SetResult (Result, TC_INCOMPATIBLE);
210                     return;
211             }
212         }
213
214         /* Check for special type elements */
215         switch (LeftType) {
216
217             case T_TYPE_PTR:
218                 ++Indirections;
219                 break;
220
221             case T_TYPE_FUNC:
222                 /* Compare the function descriptors */
223                 F1 = DecodePtr (lhs+1);
224                 F2 = DecodePtr (rhs+1);
225
226                 /* If one of the functions is implicitly declared, both
227                  * functions are considered equal. If one of the functions is
228                  * old style, and the other is empty, the functions are
229                  * considered equal.
230                  */
231                 if ((F1->Flags & FD_IMPLICIT) != 0 || (F2->Flags & FD_IMPLICIT) != 0) {
232                     Ok = 1;
233                 } else if ((F1->Flags & FD_OLDSTYLE) != 0 && (F2->Flags & FD_EMPTY) != 0) {
234                     Ok = 1;
235                 } else if ((F1->Flags & FD_EMPTY) != 0 && (F2->Flags & FD_OLDSTYLE) != 0) {
236                     Ok = 1;
237                 } else {
238                     Ok = 0;
239                 }
240
241                 if (!Ok) {
242
243                     /* Check the remaining flags */
244                     if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) {
245                         /* Flags differ */
246                         SetResult (Result, TC_INCOMPATIBLE);
247                         return;
248                     }
249
250                     /* Compare the parameter lists */
251                     if (EqualFuncParams (F1->SymTab, F2->SymTab) == 0 ||
252                         EqualSymTables (F1->TagTab, F2->TagTab) == 0) {
253                         /* One of the tables is not identical */
254                         SetResult (Result, TC_INCOMPATIBLE);
255                         return;
256                     }
257                 }
258
259                 /* Skip the FuncDesc pointers to compare the return type */
260                 lhs += DECODE_SIZE;
261                 rhs += DECODE_SIZE;
262                 break;
263
264             case T_TYPE_ARRAY:
265                 /* Check member count */
266                 LeftCount  = Decode (lhs+1);
267                 RightCount = Decode (rhs+1);
268                 if (LeftCount != 0 && RightCount != 0 && LeftCount != RightCount) {
269                     /* Member count given but different */
270                     SetResult (Result, TC_INCOMPATIBLE);
271                     return;
272                 }
273                 lhs += DECODE_SIZE;
274                 rhs += DECODE_SIZE;
275                 break;
276
277             case T_TYPE_STRUCT:
278             case T_TYPE_UNION:
279                 /* Compare the fields recursively. To do that, we fetch the
280                  * pointer to the struct definition from the type, and compare
281                  * the fields.
282                  */
283                 Sym1 = DecodePtr (lhs+1);
284                 Sym2 = DecodePtr (rhs+1);
285
286                 /* Get the field tables from the struct entry */
287                 Tab1 = Sym1->V.S.SymTab;
288                 Tab2 = Sym2->V.S.SymTab;
289
290                 /* One or both structs may be forward definitions. In this case,
291                  * the symbol tables are both non existant. Assume that the
292                  * structs are equal in this case.
293                  */
294                 if (Tab1 != 0 && Tab2 != 0) {
295
296                     if (EqualSymTables (Tab1, Tab2) == 0) {
297                         /* Field lists are not equal */
298                         SetResult (Result, TC_INCOMPATIBLE);
299                         return;
300                     }
301
302                 }
303
304                 /* Structs are equal */
305                 lhs += DECODE_SIZE;
306                 rhs += DECODE_SIZE;
307                 break;
308         }
309
310         /* Next type string element */
311         ++lhs;
312         ++rhs;
313         ++ElementCount;
314     }
315
316     /* Check if end of rhs reached */
317     if (*rhs == T_END) {
318         SetResult (Result, TC_EQUAL);
319     } else {
320         SetResult (Result, TC_INCOMPATIBLE);
321     }
322 }
323
324
325
326 typecmp_t TypeCmp (const type* lhs, const type* rhs)
327 /* Compare two types and return the result */
328 {
329     /* Assume the types are identical */
330     typecmp_t   Result = TC_IDENTICAL;
331
332 #if 0
333     printf ("Left : "); PrintRawType (stdout, lhs);
334     printf ("Right: "); PrintRawType (stdout, rhs);
335 #endif
336
337     /* Recursively compare the types if they aren't identical */
338     if (rhs != lhs) {
339         DoCompare (lhs, rhs, &Result);
340     }
341
342     /* Return the result */
343     return Result;
344 }
345
346
347