1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* datatype.c */ |
4 | /* */ |
5 | /* Type string handling for the cc65 C compiler */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 1998-2015, 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 | #include <string.h> |
37 | |
38 | /* common */ |
39 | #include "addrsize.h" |
40 | #include "check.h" |
41 | #include "mmodel.h" |
42 | #include "xmalloc.h" |
43 | |
44 | /* cc65 */ |
45 | #include "codegen.h" |
46 | #include "datatype.h" |
47 | #include "error.h" |
48 | #include "fp.h" |
49 | #include "funcdesc.h" |
50 | #include "global.h" |
51 | #include "symtab.h" |
52 | |
53 | |
54 | |
55 | /*****************************************************************************/ |
56 | /* Data */ |
57 | /*****************************************************************************/ |
58 | |
59 | |
60 | |
61 | /* Predefined type strings */ |
62 | Type type_schar[] = { TYPE(T_SCHAR), TYPE(T_END) }; |
63 | Type type_uchar[] = { TYPE(T_UCHAR), TYPE(T_END) }; |
64 | Type type_int[] = { TYPE(T_INT), TYPE(T_END) }; |
65 | Type type_uint[] = { TYPE(T_UINT), TYPE(T_END) }; |
66 | Type type_long[] = { TYPE(T_LONG), TYPE(T_END) }; |
67 | Type type_ulong[] = { TYPE(T_ULONG), TYPE(T_END) }; |
68 | Type type_void[] = { TYPE(T_VOID), TYPE(T_END) }; |
69 | Type type_size_t[] = { TYPE(T_SIZE_T), TYPE(T_END) }; |
70 | Type type_float[] = { TYPE(T_FLOAT), TYPE(T_END) }; |
71 | Type type_double[] = { TYPE(T_DOUBLE), TYPE(T_END) }; |
72 | |
73 | |
74 | |
75 | /*****************************************************************************/ |
76 | /* Code */ |
77 | /*****************************************************************************/ |
78 | |
79 | |
80 | |
81 | unsigned TypeLen (const Type* T) |
82 | /* Return the length of the type string */ |
83 | { |
84 | const Type* Start = T; |
85 | while (T->C != T_END) { |
86 | ++T; |
87 | } |
88 | return T - Start; |
89 | } |
90 | |
91 | |
92 | |
93 | Type* TypeCopy (Type* Dest, const Type* Src) |
94 | /* Copy a type string */ |
95 | { |
96 | Type* Orig = Dest; |
97 | while (1) { |
98 | *Dest = *Src; |
99 | if (Src->C == T_END) { |
100 | break; |
101 | } |
102 | Src++; |
103 | Dest++; |
104 | } |
105 | return Orig; |
106 | } |
107 | |
108 | |
109 | |
110 | Type* TypeDup (const Type* T) |
111 | /* Create a copy of the given type on the heap */ |
112 | { |
113 | unsigned Len = (TypeLen (T) + 1) * sizeof (Type); |
114 | return memcpy (xmalloc (Len), T, Len); |
115 | } |
116 | |
117 | |
118 | |
119 | Type* TypeAlloc (unsigned Len) |
120 | /* Allocate memory for a type string of length Len. Len *must* include the |
121 | ** trailing T_END. |
122 | */ |
123 | { |
124 | return xmalloc (Len * sizeof (Type)); |
125 | } |
126 | |
127 | |
128 | |
129 | void TypeFree (Type* T) |
130 | /* Free a type string */ |
131 | { |
132 | xfree (T); |
133 | } |
134 | |
135 | |
136 | |
137 | int SignExtendChar (int C) |
138 | /* Do correct sign extension of a character */ |
139 | { |
140 | if (IS_Get (&SignedChars) && (C & 0x80) != 0) { |
141 | return C | ~0xFF; |
142 | } else { |
143 | return C & 0xFF; |
144 | } |
145 | } |
146 | |
147 | |
148 | |
149 | TypeCode GetDefaultChar (void) |
150 | /* Return the default char type (signed/unsigned) depending on the settings */ |
151 | { |
152 | return IS_Get (&SignedChars)? T_SCHAR : T_UCHAR; |
153 | } |
154 | |
155 | |
156 | |
157 | Type* GetCharArrayType (unsigned Len) |
158 | /* Return the type for a char array of the given length */ |
159 | { |
160 | /* Allocate memory for the type string */ |
161 | Type* T = TypeAlloc (3); /* array/char/terminator */ |
162 | |
163 | /* Fill the type string */ |
164 | T[0].C = T_ARRAY; |
165 | T[0].A.L = Len; /* Array length is in the L attribute */ |
166 | T[1].C = GetDefaultChar (); |
167 | T[2].C = T_END; |
168 | |
169 | /* Return the new type */ |
170 | return T; |
171 | } |
172 | |
173 | |
174 | |
175 | Type* GetImplicitFuncType (void) |
176 | /* Return a type string for an inplicitly declared function */ |
177 | { |
178 | /* Get a new function descriptor */ |
179 | FuncDesc* F = NewFuncDesc (); |
180 | |
181 | /* Allocate memory for the type string */ |
182 | Type* T = TypeAlloc (3); /* func/returns int/terminator */ |
183 | |
184 | /* Prepare the function descriptor */ |
185 | F->Flags = FD_EMPTY | FD_VARIADIC; |
186 | F->SymTab = &EmptySymTab; |
187 | F->TagTab = &EmptySymTab; |
188 | |
189 | /* Fill the type string */ |
190 | T[0].C = T_FUNC | CodeAddrSizeQualifier (); |
191 | T[0].A.P = F; |
192 | T[1].C = T_INT; |
193 | T[2].C = T_END; |
194 | |
195 | /* Return the new type */ |
196 | return T; |
197 | } |
198 | |
199 | |
200 | |
201 | Type* PointerTo (const Type* T) |
202 | /* Return a type string that is "pointer to T". The type string is allocated |
203 | ** on the heap and may be freed after use. |
204 | */ |
205 | { |
206 | /* Get the size of the type string including the terminator */ |
207 | unsigned Size = TypeLen (T) + 1; |
208 | |
209 | /* Allocate the new type string */ |
210 | Type* P = TypeAlloc (Size + 1); |
211 | |
212 | /* Create the return type... */ |
213 | P[0].C = T_PTR | (T[0].C & T_QUAL_ADDRSIZE); |
214 | memcpy (P+1, T, Size * sizeof (Type)); |
215 | |
216 | /* ...and return it */ |
217 | return P; |
218 | } |
219 | |
220 | |
221 | |
222 | static TypeCode PrintTypeComp (FILE* F, TypeCode C, TypeCode Mask, const char* Name) |
223 | /* Check for a specific component of the type. If it is there, print the |
224 | ** name and remove it. Return the type with the component removed. |
225 | */ |
226 | { |
227 | if ((C & Mask) == Mask) { |
228 | fprintf (F, "%s " , Name); |
229 | C &= ~Mask; |
230 | } |
231 | return C; |
232 | } |
233 | |
234 | |
235 | |
236 | void PrintType (FILE* F, const Type* T) |
237 | /* Output translation of type array. */ |
238 | { |
239 | /* Walk over the type string */ |
240 | while (T->C != T_END) { |
241 | |
242 | /* Get the type code */ |
243 | TypeCode C = T->C; |
244 | |
245 | /* Print any qualifiers */ |
246 | C = PrintTypeComp (F, C, T_QUAL_CONST, "const" ); |
247 | C = PrintTypeComp (F, C, T_QUAL_VOLATILE, "volatile" ); |
248 | C = PrintTypeComp (F, C, T_QUAL_RESTRICT, "restrict" ); |
249 | C = PrintTypeComp (F, C, T_QUAL_NEAR, "__near__" ); |
250 | C = PrintTypeComp (F, C, T_QUAL_FAR, "__far__" ); |
251 | C = PrintTypeComp (F, C, T_QUAL_FASTCALL, "__fastcall__" ); |
252 | C = PrintTypeComp (F, C, T_QUAL_CDECL, "__cdecl__" ); |
253 | |
254 | /* Signedness. Omit the signedness specifier for long and int */ |
255 | if ((C & T_MASK_TYPE) != T_TYPE_INT && (C & T_MASK_TYPE) != T_TYPE_LONG) { |
256 | C = PrintTypeComp (F, C, T_SIGN_SIGNED, "signed" ); |
257 | } |
258 | C = PrintTypeComp (F, C, T_SIGN_UNSIGNED, "unsigned" ); |
259 | |
260 | /* Now check the real type */ |
261 | switch (C & T_MASK_TYPE) { |
262 | case T_TYPE_CHAR: |
263 | fprintf (F, "char" ); |
264 | break; |
265 | case T_TYPE_SHORT: |
266 | fprintf (F, "short" ); |
267 | break; |
268 | case T_TYPE_INT: |
269 | fprintf (F, "int" ); |
270 | break; |
271 | case T_TYPE_LONG: |
272 | fprintf (F, "long" ); |
273 | break; |
274 | case T_TYPE_LONGLONG: |
275 | fprintf (F, "long long" ); |
276 | break; |
277 | case T_TYPE_FLOAT: |
278 | fprintf (F, "float" ); |
279 | break; |
280 | case T_TYPE_DOUBLE: |
281 | fprintf (F, "double" ); |
282 | break; |
283 | case T_TYPE_VOID: |
284 | fprintf (F, "void" ); |
285 | break; |
286 | case T_TYPE_STRUCT: |
287 | fprintf (F, "struct %s" , ((SymEntry*) T->A.P)->Name); |
288 | break; |
289 | case T_TYPE_UNION: |
290 | fprintf (F, "union %s" , ((SymEntry*) T->A.P)->Name); |
291 | break; |
292 | case T_TYPE_ARRAY: |
293 | /* Recursive call */ |
294 | PrintType (F, T + 1); |
295 | if (T->A.L == UNSPECIFIED) { |
296 | fprintf (F, " []" ); |
297 | } else { |
298 | fprintf (F, " [%ld]" , T->A.L); |
299 | } |
300 | return; |
301 | case T_TYPE_PTR: |
302 | /* Recursive call */ |
303 | PrintType (F, T + 1); |
304 | fprintf (F, " *" ); |
305 | return; |
306 | case T_TYPE_FUNC: |
307 | fprintf (F, "function returning " ); |
308 | break; |
309 | default: |
310 | fprintf (F, "unknown type: %04lX" , T->C); |
311 | } |
312 | |
313 | /* Next element */ |
314 | ++T; |
315 | } |
316 | } |
317 | |
318 | |
319 | |
320 | void PrintFuncSig (FILE* F, const char* Name, Type* T) |
321 | /* Print a function signature. */ |
322 | { |
323 | /* Get the function descriptor */ |
324 | const FuncDesc* D = GetFuncDesc (T); |
325 | |
326 | /* Print a comment with the function signature */ |
327 | PrintType (F, GetFuncReturn (T)); |
328 | if (IsQualNear (T)) { |
329 | fprintf (F, " __near__" ); |
330 | } |
331 | if (IsQualFar (T)) { |
332 | fprintf (F, " __far__" ); |
333 | } |
334 | if (IsQualFastcall (T)) { |
335 | fprintf (F, " __fastcall__" ); |
336 | } |
337 | if (IsQualCDecl (T)) { |
338 | fprintf (F, " __cdecl__" ); |
339 | } |
340 | fprintf (F, " %s (" , Name); |
341 | |
342 | /* Parameters */ |
343 | if (D->Flags & FD_VOID_PARAM) { |
344 | fprintf (F, "void" ); |
345 | } else { |
346 | unsigned I; |
347 | SymEntry* E = D->SymTab->SymHead; |
348 | for (I = 0; I < D->ParamCount; ++I) { |
349 | if (I > 0) { |
350 | fprintf (F, ", " ); |
351 | } |
352 | if (SymIsRegVar (E)) { |
353 | fprintf (F, "register " ); |
354 | } |
355 | PrintType (F, E->Type); |
356 | E = E->NextSym; |
357 | } |
358 | } |
359 | |
360 | /* End of parameter list */ |
361 | fprintf (F, ")" ); |
362 | } |
363 | |
364 | |
365 | |
366 | void PrintRawType (FILE* F, const Type* T) |
367 | /* Print a type string in raw format (for debugging) */ |
368 | { |
369 | while (T->C != T_END) { |
370 | fprintf (F, "%04lX " , T->C); |
371 | ++T; |
372 | } |
373 | fprintf (F, "\n" ); |
374 | } |
375 | |
376 | |
377 | |
378 | int TypeHasAttr (const Type* T) |
379 | /* Return true if the given type has attribute data */ |
380 | { |
381 | return IsClassStruct (T) || IsTypeArray (T) || IsClassFunc (T); |
382 | } |
383 | |
384 | |
385 | |
386 | unsigned SizeOf (const Type* T) |
387 | /* Compute size of object represented by type array. */ |
388 | { |
389 | switch (UnqualifiedType (T->C)) { |
390 | |
391 | case T_VOID: |
392 | /* A void variable is a cc65 extension. |
393 | ** Get its size (in bytes). |
394 | */ |
395 | return T->A.U; |
396 | |
397 | /* Beware: There's a chance that this triggers problems in other parts |
398 | of the compiler. The solution is to fix the callers, because calling |
399 | SizeOf() with a function type as argument is bad. */ |
400 | case T_FUNC: |
401 | return 0; /* Size of function is unknown */ |
402 | |
403 | case T_SCHAR: |
404 | case T_UCHAR: |
405 | return SIZEOF_CHAR; |
406 | |
407 | case T_SHORT: |
408 | case T_USHORT: |
409 | return SIZEOF_SHORT; |
410 | |
411 | case T_INT: |
412 | case T_UINT: |
413 | return SIZEOF_INT; |
414 | |
415 | case T_PTR: |
416 | return SIZEOF_PTR; |
417 | |
418 | case T_LONG: |
419 | case T_ULONG: |
420 | return SIZEOF_LONG; |
421 | |
422 | case T_LONGLONG: |
423 | case T_ULONGLONG: |
424 | return SIZEOF_LONGLONG; |
425 | |
426 | case T_ENUM: |
427 | return SIZEOF_INT; |
428 | |
429 | case T_FLOAT: |
430 | return SIZEOF_FLOAT; |
431 | |
432 | case T_DOUBLE: |
433 | return SIZEOF_DOUBLE; |
434 | |
435 | case T_STRUCT: |
436 | case T_UNION: |
437 | return ((SymEntry*) T->A.P)->V.S.Size; |
438 | |
439 | case T_ARRAY: |
440 | if (T->A.L == UNSPECIFIED) { |
441 | /* Array with unspecified size */ |
442 | return 0; |
443 | } else { |
444 | return T->A.U * SizeOf (T + 1); |
445 | } |
446 | |
447 | default: |
448 | Internal ("Unknown type in SizeOf: %04lX" , T->C); |
449 | return 0; |
450 | |
451 | } |
452 | } |
453 | |
454 | |
455 | |
456 | unsigned PSizeOf (const Type* T) |
457 | /* Compute size of pointer object. */ |
458 | { |
459 | /* We are expecting a pointer expression */ |
460 | CHECK (IsClassPtr (T)); |
461 | |
462 | /* Skip the pointer or array token itself */ |
463 | return SizeOf (T + 1); |
464 | } |
465 | |
466 | |
467 | |
468 | unsigned CheckedSizeOf (const Type* T) |
469 | /* Return the size of a data type. If the size is zero, emit an error and |
470 | ** return some valid size instead (so the rest of the compiler doesn't have |
471 | ** to work with invalid sizes). |
472 | */ |
473 | { |
474 | unsigned Size = SizeOf (T); |
475 | if (Size == 0) { |
476 | Error ("Size of data type is unknown" ); |
477 | Size = SIZEOF_CHAR; /* Don't return zero */ |
478 | } |
479 | return Size; |
480 | } |
481 | |
482 | |
483 | |
484 | unsigned CheckedPSizeOf (const Type* T) |
485 | /* Return the size of a data type that is pointed to by a pointer. If the |
486 | ** size is zero, emit an error and return some valid size instead (so the |
487 | ** rest of the compiler doesn't have to work with invalid sizes). |
488 | */ |
489 | { |
490 | unsigned Size = PSizeOf (T); |
491 | if (Size == 0) { |
492 | Error ("Size of data type is unknown" ); |
493 | Size = SIZEOF_CHAR; /* Don't return zero */ |
494 | } |
495 | return Size; |
496 | } |
497 | |
498 | |
499 | |
500 | unsigned TypeOf (const Type* T) |
501 | /* Get the code generator base type of the object */ |
502 | { |
503 | switch (UnqualifiedType (T->C)) { |
504 | |
505 | case T_SCHAR: |
506 | return CF_CHAR; |
507 | |
508 | case T_UCHAR: |
509 | return CF_CHAR | CF_UNSIGNED; |
510 | |
511 | case T_SHORT: |
512 | case T_INT: |
513 | case T_ENUM: |
514 | return CF_INT; |
515 | |
516 | case T_USHORT: |
517 | case T_UINT: |
518 | case T_PTR: |
519 | case T_ARRAY: |
520 | return CF_INT | CF_UNSIGNED; |
521 | |
522 | case T_LONG: |
523 | return CF_LONG; |
524 | |
525 | case T_ULONG: |
526 | return CF_LONG | CF_UNSIGNED; |
527 | |
528 | case T_FLOAT: |
529 | case T_DOUBLE: |
530 | /* These two are identical in the backend */ |
531 | return CF_FLOAT; |
532 | |
533 | case T_FUNC: |
534 | return (((FuncDesc*) T->A.P)->Flags & FD_VARIADIC)? 0 : CF_FIXARGC; |
535 | |
536 | case T_STRUCT: |
537 | case T_UNION: |
538 | /* Address of ... */ |
539 | return CF_INT | CF_UNSIGNED; |
540 | |
541 | default: |
542 | Error ("Illegal type %04lX" , T->C); |
543 | return CF_INT; |
544 | } |
545 | } |
546 | |
547 | |
548 | |
549 | Type* Indirect (Type* T) |
550 | /* Do one indirection for the given type, that is, return the type where the |
551 | ** given type points to. |
552 | */ |
553 | { |
554 | /* We are expecting a pointer expression */ |
555 | CHECK (IsClassPtr (T)); |
556 | |
557 | /* Skip the pointer or array token itself */ |
558 | return T + 1; |
559 | } |
560 | |
561 | |
562 | |
563 | Type* ArrayToPtr (Type* T) |
564 | /* Convert an array to a pointer to it's first element */ |
565 | { |
566 | /* Return pointer to first element */ |
567 | return PointerTo (GetElementType (T)); |
568 | } |
569 | |
570 | |
571 | |
572 | int IsVariadicFunc (const Type* T) |
573 | /* Return true if this is a function type or pointer to function type with |
574 | ** variable parameter list |
575 | */ |
576 | { |
577 | FuncDesc* F = GetFuncDesc (T); |
578 | return (F->Flags & FD_VARIADIC) != 0; |
579 | } |
580 | |
581 | |
582 | |
583 | FuncDesc* GetFuncDesc (const Type* T) |
584 | /* Get the FuncDesc pointer from a function or pointer-to-function type */ |
585 | { |
586 | if (UnqualifiedType (T->C) == T_PTR) { |
587 | /* Pointer to function */ |
588 | ++T; |
589 | } |
590 | |
591 | /* Be sure it's a function type */ |
592 | CHECK (IsClassFunc (T)); |
593 | |
594 | /* Get the function descriptor from the type attributes */ |
595 | return T->A.P; |
596 | } |
597 | |
598 | |
599 | |
600 | void SetFuncDesc (Type* T, FuncDesc* F) |
601 | /* Set the FuncDesc pointer in a function or pointer-to-function type */ |
602 | { |
603 | if (UnqualifiedType (T->C) == T_PTR) { |
604 | /* Pointer to function */ |
605 | ++T; |
606 | } |
607 | |
608 | /* Be sure it's a function type */ |
609 | CHECK (IsClassFunc (T)); |
610 | |
611 | /* Set the function descriptor */ |
612 | T->A.P = F; |
613 | } |
614 | |
615 | |
616 | |
617 | Type* GetFuncReturn (Type* T) |
618 | /* Return a pointer to the return type of a function or pointer-to-function type */ |
619 | { |
620 | if (UnqualifiedType (T->C) == T_PTR) { |
621 | /* Pointer to function */ |
622 | ++T; |
623 | } |
624 | |
625 | /* Be sure it's a function type */ |
626 | CHECK (IsClassFunc (T)); |
627 | |
628 | /* Return a pointer to the return type */ |
629 | return T + 1; |
630 | } |
631 | |
632 | |
633 | |
634 | long GetElementCount (const Type* T) |
635 | /* Get the element count of the array specified in T (which must be of |
636 | ** array type). |
637 | */ |
638 | { |
639 | CHECK (IsTypeArray (T)); |
640 | return T->A.L; |
641 | } |
642 | |
643 | |
644 | |
645 | void SetElementCount (Type* T, long Count) |
646 | /* Set the element count of the array specified in T (which must be of |
647 | ** array type). |
648 | */ |
649 | { |
650 | CHECK (IsTypeArray (T)); |
651 | T->A.L = Count; |
652 | } |
653 | |
654 | |
655 | |
656 | Type* GetElementType (Type* T) |
657 | /* Return the element type of the given array type. */ |
658 | { |
659 | CHECK (IsTypeArray (T)); |
660 | return T + 1; |
661 | } |
662 | |
663 | |
664 | |
665 | Type* GetBaseElementType (Type* T) |
666 | /* Return the base element type of a given type. If T is not an array, this |
667 | ** will return. Otherwise it will return the base element type, which means |
668 | ** the element type that is not an array. |
669 | */ |
670 | { |
671 | while (IsTypeArray (T)) { |
672 | ++T; |
673 | } |
674 | return T; |
675 | } |
676 | |
677 | |
678 | |
679 | SymEntry* GetSymEntry (const Type* T) |
680 | /* Return a SymEntry pointer from a type */ |
681 | { |
682 | /* Only structs or unions have a SymEntry attribute */ |
683 | CHECK (IsClassStruct (T)); |
684 | |
685 | /* Return the attribute */ |
686 | return T->A.P; |
687 | } |
688 | |
689 | |
690 | |
691 | void SetSymEntry (Type* T, SymEntry* S) |
692 | /* Set the SymEntry pointer for a type */ |
693 | { |
694 | /* Only structs or unions have a SymEntry attribute */ |
695 | CHECK (IsClassStruct (T)); |
696 | |
697 | /* Set the attribute */ |
698 | T->A.P = S; |
699 | } |
700 | |
701 | |
702 | |
703 | Type* IntPromotion (Type* T) |
704 | /* Apply the integer promotions to T and return the result. The returned type |
705 | ** string may be T if there is no need to change it. |
706 | */ |
707 | { |
708 | /* We must have an int to apply int promotions */ |
709 | PRECONDITION (IsClassInt (T)); |
710 | |
711 | /* An integer can represent all values from either signed or unsigned char, |
712 | ** so convert chars to int and leave all other types alone. |
713 | */ |
714 | if (IsTypeChar (T)) { |
715 | return type_int; |
716 | } else { |
717 | return T; |
718 | } |
719 | } |
720 | |
721 | |
722 | |
723 | Type* PtrConversion (Type* T) |
724 | /* If the type is a function, convert it to pointer to function. If the |
725 | ** expression is an array, convert it to pointer to first element. Otherwise |
726 | ** return T. |
727 | */ |
728 | { |
729 | if (IsTypeFunc (T)) { |
730 | return PointerTo (T); |
731 | } else if (IsTypeArray (T)) { |
732 | return ArrayToPtr (T); |
733 | } else { |
734 | return T; |
735 | } |
736 | } |
737 | |
738 | |
739 | |
740 | TypeCode AddrSizeQualifier (unsigned AddrSize) |
741 | /* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */ |
742 | { |
743 | switch (AddrSize) { |
744 | |
745 | case ADDR_SIZE_ABS: |
746 | return T_QUAL_NEAR; |
747 | |
748 | case ADDR_SIZE_FAR: |
749 | return T_QUAL_FAR; |
750 | |
751 | default: |
752 | Error ("Invalid address size" ); |
753 | return T_QUAL_NEAR; |
754 | |
755 | } |
756 | } |
757 | |