xref: /illumos-gate/usr/src/tools/smatch/src/symbol.c (revision c85f09cc)
11f5207b7SJohn Levon /*
21f5207b7SJohn Levon  * Symbol lookup and handling.
31f5207b7SJohn Levon  *
41f5207b7SJohn Levon  * Copyright (C) 2003 Transmeta Corp.
51f5207b7SJohn Levon  *               2003-2004 Linus Torvalds
61f5207b7SJohn Levon  *
71f5207b7SJohn Levon  * Permission is hereby granted, free of charge, to any person obtaining a copy
81f5207b7SJohn Levon  * of this software and associated documentation files (the "Software"), to deal
91f5207b7SJohn Levon  * in the Software without restriction, including without limitation the rights
101f5207b7SJohn Levon  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
111f5207b7SJohn Levon  * copies of the Software, and to permit persons to whom the Software is
121f5207b7SJohn Levon  * furnished to do so, subject to the following conditions:
131f5207b7SJohn Levon  *
141f5207b7SJohn Levon  * The above copyright notice and this permission notice shall be included in
151f5207b7SJohn Levon  * all copies or substantial portions of the Software.
161f5207b7SJohn Levon  *
171f5207b7SJohn Levon  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
181f5207b7SJohn Levon  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
191f5207b7SJohn Levon  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
201f5207b7SJohn Levon  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
211f5207b7SJohn Levon  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
221f5207b7SJohn Levon  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
231f5207b7SJohn Levon  * THE SOFTWARE.
241f5207b7SJohn Levon  */
251f5207b7SJohn Levon #include <stdlib.h>
261f5207b7SJohn Levon #include <stdio.h>
271f5207b7SJohn Levon #include <string.h>
281f5207b7SJohn Levon 
291f5207b7SJohn Levon #include "lib.h"
301f5207b7SJohn Levon #include "allocate.h"
311f5207b7SJohn Levon #include "token.h"
321f5207b7SJohn Levon #include "parse.h"
331f5207b7SJohn Levon #include "symbol.h"
341f5207b7SJohn Levon #include "scope.h"
351f5207b7SJohn Levon #include "expression.h"
36*c85f09ccSJohn Levon #include "evaluate.h"
371f5207b7SJohn Levon 
381f5207b7SJohn Levon #include "target.h"
391f5207b7SJohn Levon 
401f5207b7SJohn Levon /*
411f5207b7SJohn Levon  * Secondary symbol list for stuff that needs to be output because it
421f5207b7SJohn Levon  * was used.
431f5207b7SJohn Levon  */
441f5207b7SJohn Levon struct symbol_list *translation_unit_used_list = NULL;
451f5207b7SJohn Levon 
461f5207b7SJohn Levon /*
471f5207b7SJohn Levon  * If the symbol is an inline symbol, add it to the list of symbols to parse
481f5207b7SJohn Levon  */
access_symbol(struct symbol * sym)491f5207b7SJohn Levon void access_symbol(struct symbol *sym)
501f5207b7SJohn Levon {
511f5207b7SJohn Levon 	if (sym->ctype.modifiers & MOD_INLINE) {
52*c85f09ccSJohn Levon 		if (!sym->accessed) {
531f5207b7SJohn Levon 			add_symbol(&translation_unit_used_list, sym);
54*c85f09ccSJohn Levon 			sym->accessed = 1;
551f5207b7SJohn Levon 		}
561f5207b7SJohn Levon 	}
571f5207b7SJohn Levon }
581f5207b7SJohn Levon 
lookup_symbol(struct ident * ident,enum namespace ns)591f5207b7SJohn Levon struct symbol *lookup_symbol(struct ident *ident, enum namespace ns)
601f5207b7SJohn Levon {
611f5207b7SJohn Levon 	struct symbol *sym;
621f5207b7SJohn Levon 
631f5207b7SJohn Levon 	for (sym = ident->symbols; sym; sym = sym->next_id) {
641f5207b7SJohn Levon 		if (sym->namespace & ns) {
651f5207b7SJohn Levon 			sym->used = 1;
661f5207b7SJohn Levon 			return sym;
671f5207b7SJohn Levon 		}
681f5207b7SJohn Levon 	}
691f5207b7SJohn Levon 	return NULL;
701f5207b7SJohn Levon }
711f5207b7SJohn Levon 
alloc_context(void)721f5207b7SJohn Levon struct context *alloc_context(void)
731f5207b7SJohn Levon {
741f5207b7SJohn Levon 	return __alloc_context(0);
751f5207b7SJohn Levon }
761f5207b7SJohn Levon 
alloc_symbol(struct position pos,int type)771f5207b7SJohn Levon struct symbol *alloc_symbol(struct position pos, int type)
781f5207b7SJohn Levon {
791f5207b7SJohn Levon 	struct symbol *sym = __alloc_symbol(0);
801f5207b7SJohn Levon 	sym->type = type;
811f5207b7SJohn Levon 	sym->pos = pos;
821f5207b7SJohn Levon 	sym->endpos.type = 0;
831f5207b7SJohn Levon 	return sym;
841f5207b7SJohn Levon }
851f5207b7SJohn Levon 
861f5207b7SJohn Levon struct struct_union_info {
871f5207b7SJohn Levon 	unsigned long max_align;
881f5207b7SJohn Levon 	unsigned long bit_size;
891f5207b7SJohn Levon 	int align_size;
901f5207b7SJohn Levon };
911f5207b7SJohn Levon 
921f5207b7SJohn Levon /*
931f5207b7SJohn Levon  * Unions are fairly easy to lay out ;)
941f5207b7SJohn Levon  */
lay_out_union(struct symbol * sym,struct struct_union_info * info)951f5207b7SJohn Levon static void lay_out_union(struct symbol *sym, struct struct_union_info *info)
961f5207b7SJohn Levon {
971f5207b7SJohn Levon 	examine_symbol_type(sym);
981f5207b7SJohn Levon 
991f5207b7SJohn Levon 	// Unnamed bitfields do not affect alignment.
1001f5207b7SJohn Levon 	if (sym->ident || !is_bitfield_type(sym)) {
1011f5207b7SJohn Levon 		if (sym->ctype.alignment > info->max_align)
1021f5207b7SJohn Levon 			info->max_align = sym->ctype.alignment;
1031f5207b7SJohn Levon 	}
1041f5207b7SJohn Levon 
1051f5207b7SJohn Levon 	if (sym->bit_size > info->bit_size)
1061f5207b7SJohn Levon 		info->bit_size = sym->bit_size;
1071f5207b7SJohn Levon 
1081f5207b7SJohn Levon 	sym->offset = 0;
1091f5207b7SJohn Levon }
1101f5207b7SJohn Levon 
bitfield_base_size(struct symbol * sym)1111f5207b7SJohn Levon static int bitfield_base_size(struct symbol *sym)
1121f5207b7SJohn Levon {
1131f5207b7SJohn Levon 	if (sym->type == SYM_NODE)
1141f5207b7SJohn Levon 		sym = sym->ctype.base_type;
1151f5207b7SJohn Levon 	if (sym->type == SYM_BITFIELD)
1161f5207b7SJohn Levon 		sym = sym->ctype.base_type;
1171f5207b7SJohn Levon 	return sym->bit_size;
1181f5207b7SJohn Levon }
1191f5207b7SJohn Levon 
1201f5207b7SJohn Levon /*
1211f5207b7SJohn Levon  * Structures are a bit more interesting to lay out
1221f5207b7SJohn Levon  */
lay_out_struct(struct symbol * sym,struct struct_union_info * info)1231f5207b7SJohn Levon static void lay_out_struct(struct symbol *sym, struct struct_union_info *info)
1241f5207b7SJohn Levon {
1251f5207b7SJohn Levon 	unsigned long bit_size, align_bit_mask;
1261f5207b7SJohn Levon 	int base_size;
1271f5207b7SJohn Levon 
1281f5207b7SJohn Levon 	examine_symbol_type(sym);
1291f5207b7SJohn Levon 
1301f5207b7SJohn Levon 	// Unnamed bitfields do not affect alignment.
1311f5207b7SJohn Levon 	if (sym->ident || !is_bitfield_type(sym)) {
1321f5207b7SJohn Levon 		if (sym->ctype.alignment > info->max_align)
1331f5207b7SJohn Levon 			info->max_align = sym->ctype.alignment;
1341f5207b7SJohn Levon 	}
1351f5207b7SJohn Levon 
1361f5207b7SJohn Levon 	bit_size = info->bit_size;
1371f5207b7SJohn Levon 	base_size = sym->bit_size;
1381f5207b7SJohn Levon 
1391f5207b7SJohn Levon 	/*
1401f5207b7SJohn Levon 	 * Unsized arrays cause us to not align the resulting
1411f5207b7SJohn Levon 	 * structure size
1421f5207b7SJohn Levon 	 */
1431f5207b7SJohn Levon 	if (base_size < 0) {
1441f5207b7SJohn Levon 		info->align_size = 0;
1451f5207b7SJohn Levon 		base_size = 0;
1461f5207b7SJohn Levon 	}
1471f5207b7SJohn Levon 
1481f5207b7SJohn Levon 	align_bit_mask = bytes_to_bits(sym->ctype.alignment) - 1;
1491f5207b7SJohn Levon 
1501f5207b7SJohn Levon 	/*
1511f5207b7SJohn Levon 	 * Bitfields have some very special rules..
1521f5207b7SJohn Levon 	 */
1531f5207b7SJohn Levon 	if (is_bitfield_type (sym)) {
1541f5207b7SJohn Levon 		unsigned long bit_offset = bit_size & align_bit_mask;
1551f5207b7SJohn Levon 		int room = bitfield_base_size(sym) - bit_offset;
1561f5207b7SJohn Levon 		// Zero-width fields just fill up the unit.
1571f5207b7SJohn Levon 		int width = base_size ? : (bit_offset ? room : 0);
1581f5207b7SJohn Levon 
1591f5207b7SJohn Levon 		if (width > room) {
1601f5207b7SJohn Levon 			bit_size = (bit_size + align_bit_mask) & ~align_bit_mask;
1611f5207b7SJohn Levon 			bit_offset = 0;
1621f5207b7SJohn Levon 		}
1631f5207b7SJohn Levon 		sym->offset = bits_to_bytes(bit_size - bit_offset);
1641f5207b7SJohn Levon 		sym->bit_offset = bit_offset;
1651f5207b7SJohn Levon 		sym->ctype.base_type->bit_offset = bit_offset;
1661f5207b7SJohn Levon 		info->bit_size = bit_size + width;
1671f5207b7SJohn Levon 		// warning (sym->pos, "bitfield: offset=%d:%d  size=:%d", sym->offset, sym->bit_offset, width);
1681f5207b7SJohn Levon 
1691f5207b7SJohn Levon 		return;
1701f5207b7SJohn Levon 	}
1711f5207b7SJohn Levon 
1721f5207b7SJohn Levon 	/*
1731f5207b7SJohn Levon 	 * Otherwise, just align it right and add it up..
1741f5207b7SJohn Levon 	 */
1751f5207b7SJohn Levon 	bit_size = (bit_size + align_bit_mask) & ~align_bit_mask;
1761f5207b7SJohn Levon 	sym->offset = bits_to_bytes(bit_size);
1771f5207b7SJohn Levon 
1781f5207b7SJohn Levon 	info->bit_size = bit_size + base_size;
1791f5207b7SJohn Levon 	// warning (sym->pos, "regular: offset=%d", sym->offset);
1801f5207b7SJohn Levon }
1811f5207b7SJohn Levon 
examine_struct_union_type(struct symbol * sym,int advance)1821f5207b7SJohn Levon static struct symbol * examine_struct_union_type(struct symbol *sym, int advance)
1831f5207b7SJohn Levon {
1841f5207b7SJohn Levon 	struct struct_union_info info = {
1851f5207b7SJohn Levon 		.max_align = 1,
1861f5207b7SJohn Levon 		.bit_size = 0,
1871f5207b7SJohn Levon 		.align_size = 1
1881f5207b7SJohn Levon 	};
1891f5207b7SJohn Levon 	unsigned long bit_size, bit_align;
1901f5207b7SJohn Levon 	void (*fn)(struct symbol *, struct struct_union_info *);
1911f5207b7SJohn Levon 	struct symbol *member;
1921f5207b7SJohn Levon 
1931f5207b7SJohn Levon 	fn = advance ? lay_out_struct : lay_out_union;
1941f5207b7SJohn Levon 	FOR_EACH_PTR(sym->symbol_list, member) {
1951f5207b7SJohn Levon 		fn(member, &info);
1961f5207b7SJohn Levon 	} END_FOR_EACH_PTR(member);
1971f5207b7SJohn Levon 
1981f5207b7SJohn Levon 	if (!sym->ctype.alignment)
1991f5207b7SJohn Levon 		sym->ctype.alignment = info.max_align;
2001f5207b7SJohn Levon 	bit_size = info.bit_size;
2011f5207b7SJohn Levon 	if (info.align_size) {
2021f5207b7SJohn Levon 		bit_align = bytes_to_bits(sym->ctype.alignment)-1;
2031f5207b7SJohn Levon 		bit_size = (bit_size + bit_align) & ~bit_align;
2041f5207b7SJohn Levon 	}
2051f5207b7SJohn Levon 	sym->bit_size = bit_size;
2061f5207b7SJohn Levon 	return sym;
2071f5207b7SJohn Levon }
2081f5207b7SJohn Levon 
examine_base_type(struct symbol * sym)2091f5207b7SJohn Levon static struct symbol *examine_base_type(struct symbol *sym)
2101f5207b7SJohn Levon {
2111f5207b7SJohn Levon 	struct symbol *base_type;
2121f5207b7SJohn Levon 
2131f5207b7SJohn Levon 	/* Check the base type */
2141f5207b7SJohn Levon 	base_type = examine_symbol_type(sym->ctype.base_type);
2151f5207b7SJohn Levon 	if (!base_type || base_type->type == SYM_PTR)
2161f5207b7SJohn Levon 		return base_type;
217*c85f09ccSJohn Levon 	combine_address_space(sym->pos, &sym->ctype.as, base_type->ctype.as);
2181f5207b7SJohn Levon 	sym->ctype.modifiers |= base_type->ctype.modifiers & MOD_PTRINHERIT;
2191f5207b7SJohn Levon 	concat_ptr_list((struct ptr_list *)base_type->ctype.contexts,
2201f5207b7SJohn Levon 			(struct ptr_list **)&sym->ctype.contexts);
2211f5207b7SJohn Levon 	if (base_type->type == SYM_NODE) {
2221f5207b7SJohn Levon 		base_type = base_type->ctype.base_type;
2231f5207b7SJohn Levon 		sym->ctype.base_type = base_type;
2241f5207b7SJohn Levon 	}
2251f5207b7SJohn Levon 	return base_type;
2261f5207b7SJohn Levon }
2271f5207b7SJohn Levon 
examine_array_type(struct symbol * sym)2281f5207b7SJohn Levon static struct symbol * examine_array_type(struct symbol *sym)
2291f5207b7SJohn Levon {
2301f5207b7SJohn Levon 	struct symbol *base_type = examine_base_type(sym);
2311f5207b7SJohn Levon 	unsigned long bit_size = -1, alignment;
2321f5207b7SJohn Levon 	struct expression *array_size = sym->array_size;
2331f5207b7SJohn Levon 
2341f5207b7SJohn Levon 	if (!base_type)
2351f5207b7SJohn Levon 		return sym;
2361f5207b7SJohn Levon 
2371f5207b7SJohn Levon 	if (array_size) {
2381f5207b7SJohn Levon 		bit_size = array_element_offset(base_type->bit_size,
2391f5207b7SJohn Levon 						get_expression_value_silent(array_size));
2401f5207b7SJohn Levon 		if (array_size->type != EXPR_VALUE) {
2411f5207b7SJohn Levon 			if (Wvla)
2421f5207b7SJohn Levon 				warning(array_size->pos, "Variable length array is used.");
2431f5207b7SJohn Levon 			bit_size = -1;
2441f5207b7SJohn Levon 		}
2451f5207b7SJohn Levon 	}
2461f5207b7SJohn Levon 	alignment = base_type->ctype.alignment;
2471f5207b7SJohn Levon 	if (!sym->ctype.alignment)
2481f5207b7SJohn Levon 		sym->ctype.alignment = alignment;
2491f5207b7SJohn Levon 	sym->bit_size = bit_size;
2501f5207b7SJohn Levon 	return sym;
2511f5207b7SJohn Levon }
2521f5207b7SJohn Levon 
examine_bitfield_type(struct symbol * sym)2531f5207b7SJohn Levon static struct symbol *examine_bitfield_type(struct symbol *sym)
2541f5207b7SJohn Levon {
2551f5207b7SJohn Levon 	struct symbol *base_type = examine_base_type(sym);
2561f5207b7SJohn Levon 	unsigned long bit_size, alignment, modifiers;
2571f5207b7SJohn Levon 
2581f5207b7SJohn Levon 	if (!base_type)
2591f5207b7SJohn Levon 		return sym;
2601f5207b7SJohn Levon 	bit_size = base_type->bit_size;
2611f5207b7SJohn Levon 	if (sym->bit_size > bit_size)
2621f5207b7SJohn Levon 		warning(sym->pos, "impossible field-width, %d, for this type",  sym->bit_size);
2631f5207b7SJohn Levon 
2641f5207b7SJohn Levon 	alignment = base_type->ctype.alignment;
2651f5207b7SJohn Levon 	if (!sym->ctype.alignment)
2661f5207b7SJohn Levon 		sym->ctype.alignment = alignment;
2671f5207b7SJohn Levon 	modifiers = base_type->ctype.modifiers;
2681f5207b7SJohn Levon 
2691f5207b7SJohn Levon 	/* Bitfields are unsigned, unless the base type was explicitly signed */
2701f5207b7SJohn Levon 	if (!(modifiers & MOD_EXPLICITLY_SIGNED))
2711f5207b7SJohn Levon 		modifiers = (modifiers & ~MOD_SIGNED) | MOD_UNSIGNED;
2721f5207b7SJohn Levon 	sym->ctype.modifiers |= modifiers & MOD_SIGNEDNESS;
2731f5207b7SJohn Levon 	return sym;
2741f5207b7SJohn Levon }
2751f5207b7SJohn Levon 
2761f5207b7SJohn Levon /*
2771f5207b7SJohn Levon  * "typeof" will have to merge the types together
2781f5207b7SJohn Levon  */
merge_type(struct symbol * sym,struct symbol * base_type)2791f5207b7SJohn Levon void merge_type(struct symbol *sym, struct symbol *base_type)
2801f5207b7SJohn Levon {
281*c85f09ccSJohn Levon 	combine_address_space(sym->pos, &sym->ctype.as, base_type->ctype.as);
2821f5207b7SJohn Levon 	sym->ctype.modifiers |= (base_type->ctype.modifiers & ~MOD_STORAGE);
2831f5207b7SJohn Levon 	concat_ptr_list((struct ptr_list *)base_type->ctype.contexts,
2841f5207b7SJohn Levon 	                (struct ptr_list **)&sym->ctype.contexts);
2851f5207b7SJohn Levon 	sym->ctype.base_type = base_type->ctype.base_type;
2861f5207b7SJohn Levon 	if (sym->ctype.base_type->type == SYM_NODE)
2871f5207b7SJohn Levon 		merge_type(sym, sym->ctype.base_type);
2881f5207b7SJohn Levon }
2891f5207b7SJohn Levon 
count_array_initializer(struct symbol * t,struct expression * expr)2901f5207b7SJohn Levon static int count_array_initializer(struct symbol *t, struct expression *expr)
2911f5207b7SJohn Levon {
2921f5207b7SJohn Levon 	int nr = 0;
2931f5207b7SJohn Levon 	int is_char = 0;
2941f5207b7SJohn Levon 
2951f5207b7SJohn Levon 	/*
2961f5207b7SJohn Levon 	 * Arrays of character types are special; they can be initialized by
2971f5207b7SJohn Levon 	 * string literal _or_ by string literal in braces.  The latter means
2981f5207b7SJohn Levon 	 * that with T x[] = {<string literal>} number of elements in x depends
2991f5207b7SJohn Levon 	 * on T - if it's a character type, we get the length of string literal
3001f5207b7SJohn Levon 	 * (including NUL), otherwise we have one element here.
3011f5207b7SJohn Levon 	 */
3021f5207b7SJohn Levon 	if (t->ctype.base_type == &int_type && t->ctype.modifiers & MOD_CHAR)
3031f5207b7SJohn Levon 		is_char = 1;
3041f5207b7SJohn Levon 
3051f5207b7SJohn Levon 	switch (expr->type) {
3061f5207b7SJohn Levon 	case EXPR_INITIALIZER: {
3071f5207b7SJohn Levon 		struct expression *entry;
3081f5207b7SJohn Levon 		int count = 0;
3091f5207b7SJohn Levon 		int str_len = 0;
3101f5207b7SJohn Levon 		FOR_EACH_PTR(expr->expr_list, entry) {
3111f5207b7SJohn Levon 			count++;
3121f5207b7SJohn Levon 			switch (entry->type) {
3131f5207b7SJohn Levon 			case EXPR_INDEX:
3141f5207b7SJohn Levon 				if (entry->idx_to >= nr)
3151f5207b7SJohn Levon 					nr = entry->idx_to+1;
3161f5207b7SJohn Levon 				break;
3171f5207b7SJohn Levon 			case EXPR_PREOP: {
3181f5207b7SJohn Levon 				struct expression *e = entry;
3191f5207b7SJohn Levon 				if (is_char) {
3201f5207b7SJohn Levon 					while (e && e->type == EXPR_PREOP && e->op == '(')
3211f5207b7SJohn Levon 						e = e->unop;
3221f5207b7SJohn Levon 					if (e && e->type == EXPR_STRING) {
3231f5207b7SJohn Levon 						entry = e;
3241f5207b7SJohn Levon 			case EXPR_STRING:
3251f5207b7SJohn Levon 						if (is_char)
3261f5207b7SJohn Levon 							str_len = entry->string->length;
3271f5207b7SJohn Levon 					}
3281f5207b7SJohn Levon 
3291f5207b7SJohn Levon 
3301f5207b7SJohn Levon 				}
3311f5207b7SJohn Levon 			}
3321f5207b7SJohn Levon 			default:
3331f5207b7SJohn Levon 				nr++;
3341f5207b7SJohn Levon 			}
3351f5207b7SJohn Levon 		} END_FOR_EACH_PTR(entry);
3361f5207b7SJohn Levon 		if (count == 1 && str_len)
3371f5207b7SJohn Levon 			nr = str_len;
3381f5207b7SJohn Levon 		break;
3391f5207b7SJohn Levon 	}
3401f5207b7SJohn Levon 	case EXPR_PREOP:
3411f5207b7SJohn Levon 		if (is_char) {
3421f5207b7SJohn Levon 			struct expression *e = expr;
3431f5207b7SJohn Levon 			while (e && e->type == EXPR_PREOP && e->op == '(')
3441f5207b7SJohn Levon 				e = e->unop;
3451f5207b7SJohn Levon 			if (e && e->type == EXPR_STRING) {
3461f5207b7SJohn Levon 				expr = e;
3471f5207b7SJohn Levon 	case EXPR_STRING:
3481f5207b7SJohn Levon 				if (is_char)
3491f5207b7SJohn Levon 					nr = expr->string->length;
3501f5207b7SJohn Levon 			}
3511f5207b7SJohn Levon 		}
3521f5207b7SJohn Levon 		break;
3531f5207b7SJohn Levon 	default:
3541f5207b7SJohn Levon 		break;
3551f5207b7SJohn Levon 	}
3561f5207b7SJohn Levon 	return nr;
3571f5207b7SJohn Levon }
3581f5207b7SJohn Levon 
get_symbol_initializer(struct symbol * sym)3591f5207b7SJohn Levon static struct expression *get_symbol_initializer(struct symbol *sym)
3601f5207b7SJohn Levon {
3611f5207b7SJohn Levon 	do {
3621f5207b7SJohn Levon 		if (sym->initializer)
3631f5207b7SJohn Levon 			return sym->initializer;
3641f5207b7SJohn Levon 	} while ((sym = sym->same_symbol) != NULL);
3651f5207b7SJohn Levon 	return NULL;
3661f5207b7SJohn Levon }
3671f5207b7SJohn Levon 
implicit_array_size(struct symbol * node,unsigned int count)368*c85f09ccSJohn Levon static unsigned int implicit_array_size(struct symbol *node, unsigned int count)
369*c85f09ccSJohn Levon {
370*c85f09ccSJohn Levon 	struct symbol *arr_ori = node->ctype.base_type;
371*c85f09ccSJohn Levon 	struct symbol *arr_new = alloc_symbol(node->pos, SYM_ARRAY);
372*c85f09ccSJohn Levon 	struct symbol *elem_type = arr_ori->ctype.base_type;
373*c85f09ccSJohn Levon 	struct expression *size = alloc_const_expression(node->pos, count);
374*c85f09ccSJohn Levon 	unsigned int bit_size = array_element_offset(elem_type->bit_size, count);
375*c85f09ccSJohn Levon 
376*c85f09ccSJohn Levon 	*arr_new = *arr_ori;
377*c85f09ccSJohn Levon 	arr_new->bit_size = bit_size;
378*c85f09ccSJohn Levon 	arr_new->array_size = size;
379*c85f09ccSJohn Levon 	node->array_size = size;
380*c85f09ccSJohn Levon 	node->ctype.base_type = arr_new;
381*c85f09ccSJohn Levon 
382*c85f09ccSJohn Levon 	return bit_size;
383*c85f09ccSJohn Levon }
384*c85f09ccSJohn Levon 
examine_node_type(struct symbol * sym)3851f5207b7SJohn Levon static struct symbol * examine_node_type(struct symbol *sym)
3861f5207b7SJohn Levon {
3871f5207b7SJohn Levon 	struct symbol *base_type = examine_base_type(sym);
3881f5207b7SJohn Levon 	int bit_size;
3891f5207b7SJohn Levon 	unsigned long alignment;
3901f5207b7SJohn Levon 
3911f5207b7SJohn Levon 	/* SYM_NODE - figure out what the type of the node was.. */
3921f5207b7SJohn Levon 	bit_size = 0;
3931f5207b7SJohn Levon 	alignment = 0;
3941f5207b7SJohn Levon 	if (!base_type)
3951f5207b7SJohn Levon 		return sym;
3961f5207b7SJohn Levon 
3971f5207b7SJohn Levon 	bit_size = base_type->bit_size;
3981f5207b7SJohn Levon 	alignment = base_type->ctype.alignment;
3991f5207b7SJohn Levon 
4001f5207b7SJohn Levon 	/* Pick up signedness information into the node */
4011f5207b7SJohn Levon 	sym->ctype.modifiers |= (MOD_SIGNEDNESS & base_type->ctype.modifiers);
4021f5207b7SJohn Levon 
4031f5207b7SJohn Levon 	if (!sym->ctype.alignment)
4041f5207b7SJohn Levon 		sym->ctype.alignment = alignment;
4051f5207b7SJohn Levon 
4061f5207b7SJohn Levon 	/* Unsized array? The size might come from the initializer.. */
4071f5207b7SJohn Levon 	if (bit_size < 0 && base_type->type == SYM_ARRAY) {
4081f5207b7SJohn Levon 		struct expression *initializer = get_symbol_initializer(sym);
4091f5207b7SJohn Levon 		if (initializer) {
4101f5207b7SJohn Levon 			struct symbol *node_type = base_type->ctype.base_type;
4111f5207b7SJohn Levon 			int count = count_array_initializer(node_type, initializer);
4121f5207b7SJohn Levon 
4131f5207b7SJohn Levon 			if (node_type && node_type->bit_size >= 0)
414*c85f09ccSJohn Levon 				bit_size = implicit_array_size(sym, count);
4151f5207b7SJohn Levon 		}
4161f5207b7SJohn Levon 	}
4171f5207b7SJohn Levon 
4181f5207b7SJohn Levon 	sym->bit_size = bit_size;
4191f5207b7SJohn Levon 	return sym;
4201f5207b7SJohn Levon }
4211f5207b7SJohn Levon 
examine_enum_type(struct symbol * sym)4221f5207b7SJohn Levon static struct symbol *examine_enum_type(struct symbol *sym)
4231f5207b7SJohn Levon {
4241f5207b7SJohn Levon 	struct symbol *base_type = examine_base_type(sym);
4251f5207b7SJohn Levon 
4261f5207b7SJohn Levon 	sym->ctype.modifiers |= (base_type->ctype.modifiers & MOD_SIGNEDNESS);
4271f5207b7SJohn Levon 	sym->bit_size = bits_in_enum;
4281f5207b7SJohn Levon 	if (base_type->bit_size > sym->bit_size)
4291f5207b7SJohn Levon 		sym->bit_size = base_type->bit_size;
4301f5207b7SJohn Levon 	sym->ctype.alignment = enum_alignment;
4311f5207b7SJohn Levon 	if (base_type->ctype.alignment > sym->ctype.alignment)
4321f5207b7SJohn Levon 		sym->ctype.alignment = base_type->ctype.alignment;
4331f5207b7SJohn Levon 	return sym;
4341f5207b7SJohn Levon }
4351f5207b7SJohn Levon 
examine_pointer_type(struct symbol * sym)4361f5207b7SJohn Levon static struct symbol *examine_pointer_type(struct symbol *sym)
4371f5207b7SJohn Levon {
4381f5207b7SJohn Levon 	/*
4391f5207b7SJohn Levon 	 * We need to set the pointer size first, and
4401f5207b7SJohn Levon 	 * examine the thing we point to only afterwards.
4411f5207b7SJohn Levon 	 * That's because this pointer type may end up
4421f5207b7SJohn Levon 	 * being needed for the base type size evaluation.
4431f5207b7SJohn Levon 	 */
4441f5207b7SJohn Levon 	if (!sym->bit_size)
4451f5207b7SJohn Levon 		sym->bit_size = bits_in_pointer;
4461f5207b7SJohn Levon 	if (!sym->ctype.alignment)
4471f5207b7SJohn Levon 		sym->ctype.alignment = pointer_alignment;
4481f5207b7SJohn Levon 	return sym;
4491f5207b7SJohn Levon }
4501f5207b7SJohn Levon 
4511f5207b7SJohn Levon /*
4521f5207b7SJohn Levon  * Fill in type size and alignment information for
4531f5207b7SJohn Levon  * regular SYM_TYPE things.
4541f5207b7SJohn Levon  */
examine_symbol_type(struct symbol * sym)4551f5207b7SJohn Levon struct symbol *examine_symbol_type(struct symbol * sym)
4561f5207b7SJohn Levon {
4571f5207b7SJohn Levon 	if (!sym)
4581f5207b7SJohn Levon 		return sym;
4591f5207b7SJohn Levon 
4601f5207b7SJohn Levon 	/* Already done? */
4611f5207b7SJohn Levon 	if (sym->examined)
4621f5207b7SJohn Levon 		return sym;
4631f5207b7SJohn Levon 	sym->examined = 1;
4641f5207b7SJohn Levon 
4651f5207b7SJohn Levon 	switch (sym->type) {
4661f5207b7SJohn Levon 	case SYM_FN:
4671f5207b7SJohn Levon 	case SYM_NODE:
4681f5207b7SJohn Levon 		return examine_node_type(sym);
4691f5207b7SJohn Levon 	case SYM_ARRAY:
4701f5207b7SJohn Levon 		return examine_array_type(sym);
4711f5207b7SJohn Levon 	case SYM_STRUCT:
4721f5207b7SJohn Levon 		return examine_struct_union_type(sym, 1);
4731f5207b7SJohn Levon 	case SYM_UNION:
4741f5207b7SJohn Levon 		return examine_struct_union_type(sym, 0);
4751f5207b7SJohn Levon 	case SYM_PTR:
4761f5207b7SJohn Levon 		return examine_pointer_type(sym);
4771f5207b7SJohn Levon 	case SYM_ENUM:
4781f5207b7SJohn Levon 		return examine_enum_type(sym);
4791f5207b7SJohn Levon 	case SYM_BITFIELD:
4801f5207b7SJohn Levon 		return examine_bitfield_type(sym);
4811f5207b7SJohn Levon 	case SYM_BASETYPE:
4821f5207b7SJohn Levon 		/* Size and alignment had better already be set up */
4831f5207b7SJohn Levon 		return sym;
4841f5207b7SJohn Levon 	case SYM_TYPEOF: {
4851f5207b7SJohn Levon 		struct symbol *base = evaluate_expression(sym->initializer);
4861f5207b7SJohn Levon 		if (base) {
4871f5207b7SJohn Levon 			unsigned long mod = 0;
4881f5207b7SJohn Levon 
4891f5207b7SJohn Levon 			if (is_bitfield_type(base))
4901f5207b7SJohn Levon 				warning(base->pos, "typeof applied to bitfield type");
4911f5207b7SJohn Levon 			if (base->type == SYM_NODE) {
4921f5207b7SJohn Levon 				mod |= base->ctype.modifiers & MOD_TYPEOF;
4931f5207b7SJohn Levon 				base = base->ctype.base_type;
4941f5207b7SJohn Levon 			}
4951f5207b7SJohn Levon 			sym->type = SYM_NODE;
4961f5207b7SJohn Levon 			sym->ctype.modifiers = mod;
4971f5207b7SJohn Levon 			sym->ctype.base_type = base;
4981f5207b7SJohn Levon 			return examine_node_type(sym);
4991f5207b7SJohn Levon 		}
500*c85f09ccSJohn Levon 		sym->type = SYM_NODE;
501*c85f09ccSJohn Levon 		sym->ctype.base_type = &bad_ctype;
502*c85f09ccSJohn Levon 		return sym;
5031f5207b7SJohn Levon 	}
5041f5207b7SJohn Levon 	case SYM_PREPROCESSOR:
5051f5207b7SJohn Levon 		sparse_error(sym->pos, "ctype on preprocessor command? (%s)", show_ident(sym->ident));
5061f5207b7SJohn Levon 		return NULL;
5071f5207b7SJohn Levon 	case SYM_UNINITIALIZED:
508*c85f09ccSJohn Levon //		sparse_error(sym->pos, "ctype on uninitialized symbol '%s'", show_typename(sym));
5091f5207b7SJohn Levon 		return NULL;
5101f5207b7SJohn Levon 	case SYM_RESTRICT:
5111f5207b7SJohn Levon 		examine_base_type(sym);
5121f5207b7SJohn Levon 		return sym;
5131f5207b7SJohn Levon 	case SYM_FOULED:
5141f5207b7SJohn Levon 		examine_base_type(sym);
5151f5207b7SJohn Levon 		return sym;
5161f5207b7SJohn Levon 	default:
5171f5207b7SJohn Levon //		sparse_error(sym->pos, "Examining unknown symbol type %d", sym->type);
5181f5207b7SJohn Levon 		break;
5191f5207b7SJohn Levon 	}
5201f5207b7SJohn Levon 	return sym;
5211f5207b7SJohn Levon }
5221f5207b7SJohn Levon 
get_type_name(enum type type)5231f5207b7SJohn Levon const char* get_type_name(enum type type)
5241f5207b7SJohn Levon {
5251f5207b7SJohn Levon 	const char *type_lookup[] = {
5261f5207b7SJohn Levon 	[SYM_UNINITIALIZED] = "uninitialized",
5271f5207b7SJohn Levon 	[SYM_PREPROCESSOR] = "preprocessor",
5281f5207b7SJohn Levon 	[SYM_BASETYPE] = "basetype",
5291f5207b7SJohn Levon 	[SYM_NODE] = "node",
5301f5207b7SJohn Levon 	[SYM_PTR] = "pointer",
5311f5207b7SJohn Levon 	[SYM_FN] = "function",
5321f5207b7SJohn Levon 	[SYM_ARRAY] = "array",
5331f5207b7SJohn Levon 	[SYM_STRUCT] = "struct",
5341f5207b7SJohn Levon 	[SYM_UNION] = "union",
5351f5207b7SJohn Levon 	[SYM_ENUM] = "enum",
5361f5207b7SJohn Levon 	[SYM_TYPEDEF] = "typedef",
5371f5207b7SJohn Levon 	[SYM_TYPEOF] = "typeof",
5381f5207b7SJohn Levon 	[SYM_MEMBER] = "member",
5391f5207b7SJohn Levon 	[SYM_BITFIELD] = "bitfield",
5401f5207b7SJohn Levon 	[SYM_LABEL] = "label",
5411f5207b7SJohn Levon 	[SYM_RESTRICT] = "restrict",
5421f5207b7SJohn Levon 	[SYM_FOULED] = "fouled",
5431f5207b7SJohn Levon 	[SYM_KEYWORD] = "keyword",
5441f5207b7SJohn Levon 	[SYM_BAD] = "bad"};
5451f5207b7SJohn Levon 
5461f5207b7SJohn Levon 	if (type <= SYM_BAD)
5471f5207b7SJohn Levon 		return type_lookup[type];
5481f5207b7SJohn Levon 	else
5491f5207b7SJohn Levon 		return NULL;
5501f5207b7SJohn Levon }
5511f5207b7SJohn Levon 
examine_pointer_target(struct symbol * sym)5521f5207b7SJohn Levon struct symbol *examine_pointer_target(struct symbol *sym)
5531f5207b7SJohn Levon {
5541f5207b7SJohn Levon 	return examine_base_type(sym);
5551f5207b7SJohn Levon }
5561f5207b7SJohn Levon 
5571f5207b7SJohn Levon static struct symbol_list *restr, *fouled;
5581f5207b7SJohn Levon 
create_fouled(struct symbol * type)5591f5207b7SJohn Levon void create_fouled(struct symbol *type)
5601f5207b7SJohn Levon {
5611f5207b7SJohn Levon 	if (type->bit_size < bits_in_int) {
5621f5207b7SJohn Levon 		struct symbol *new = alloc_symbol(type->pos, type->type);
5631f5207b7SJohn Levon 		*new = *type;
5641f5207b7SJohn Levon 		new->bit_size = bits_in_int;
5651f5207b7SJohn Levon 		new->type = SYM_FOULED;
5661f5207b7SJohn Levon 		new->ctype.base_type = type;
5671f5207b7SJohn Levon 		add_symbol(&restr, type);
5681f5207b7SJohn Levon 		add_symbol(&fouled, new);
5691f5207b7SJohn Levon 	}
5701f5207b7SJohn Levon }
5711f5207b7SJohn Levon 
befoul(struct symbol * type)5721f5207b7SJohn Levon struct symbol *befoul(struct symbol *type)
5731f5207b7SJohn Levon {
5741f5207b7SJohn Levon 	struct symbol *t1, *t2;
5751f5207b7SJohn Levon 	while (type->type == SYM_NODE)
5761f5207b7SJohn Levon 		type = type->ctype.base_type;
5771f5207b7SJohn Levon 	PREPARE_PTR_LIST(restr, t1);
5781f5207b7SJohn Levon 	PREPARE_PTR_LIST(fouled, t2);
5791f5207b7SJohn Levon 	for (;;) {
5801f5207b7SJohn Levon 		if (t1 == type)
5811f5207b7SJohn Levon 			return t2;
5821f5207b7SJohn Levon 		if (!t1)
5831f5207b7SJohn Levon 			break;
5841f5207b7SJohn Levon 		NEXT_PTR_LIST(t1);
5851f5207b7SJohn Levon 		NEXT_PTR_LIST(t2);
5861f5207b7SJohn Levon 	}
5871f5207b7SJohn Levon 	FINISH_PTR_LIST(t2);
5881f5207b7SJohn Levon 	FINISH_PTR_LIST(t1);
5891f5207b7SJohn Levon 	return NULL;
5901f5207b7SJohn Levon }
5911f5207b7SJohn Levon 
check_declaration(struct symbol * sym)5921f5207b7SJohn Levon void check_declaration(struct symbol *sym)
5931f5207b7SJohn Levon {
5941f5207b7SJohn Levon 	int warned = 0;
5951f5207b7SJohn Levon 	struct symbol *next = sym;
5961f5207b7SJohn Levon 
5971f5207b7SJohn Levon 	while ((next = next->next_id) != NULL) {
5981f5207b7SJohn Levon 		if (next->namespace != sym->namespace)
5991f5207b7SJohn Levon 			continue;
6001f5207b7SJohn Levon 		if (sym->scope == next->scope) {
6011f5207b7SJohn Levon 			sym->same_symbol = next;
6021f5207b7SJohn Levon 			return;
6031f5207b7SJohn Levon 		}
6041f5207b7SJohn Levon 		/* Extern in block level matches a TOPLEVEL non-static symbol */
6051f5207b7SJohn Levon 		if (sym->ctype.modifiers & MOD_EXTERN) {
6061f5207b7SJohn Levon 			if ((next->ctype.modifiers & (MOD_TOPLEVEL|MOD_STATIC)) == MOD_TOPLEVEL) {
6071f5207b7SJohn Levon 				sym->same_symbol = next;
6081f5207b7SJohn Levon 				return;
6091f5207b7SJohn Levon 			}
6101f5207b7SJohn Levon 		}
6111f5207b7SJohn Levon 
6121f5207b7SJohn Levon 		if (!Wshadow || warned)
6131f5207b7SJohn Levon 			continue;
6141f5207b7SJohn Levon 		if (get_sym_type(next) == SYM_FN)
6151f5207b7SJohn Levon 			continue;
6161f5207b7SJohn Levon 		warned = 1;
6171f5207b7SJohn Levon 		warning(sym->pos, "symbol '%s' shadows an earlier one", show_ident(sym->ident));
6181f5207b7SJohn Levon 		info(next->pos, "originally declared here");
6191f5207b7SJohn Levon 	}
6201f5207b7SJohn Levon }
6211f5207b7SJohn Levon 
bind_symbol(struct symbol * sym,struct ident * ident,enum namespace ns)6221f5207b7SJohn Levon void bind_symbol(struct symbol *sym, struct ident *ident, enum namespace ns)
6231f5207b7SJohn Levon {
6241f5207b7SJohn Levon 	struct scope *scope;
6251f5207b7SJohn Levon 	if (sym->bound) {
6261f5207b7SJohn Levon 		sparse_error(sym->pos, "internal error: symbol type already bound");
6271f5207b7SJohn Levon 		return;
6281f5207b7SJohn Levon 	}
6291f5207b7SJohn Levon 	if (ident->reserved && (ns & (NS_TYPEDEF | NS_STRUCT | NS_LABEL | NS_SYMBOL))) {
6301f5207b7SJohn Levon 		sparse_error(sym->pos, "Trying to use reserved word '%s' as identifier", show_ident(ident));
6311f5207b7SJohn Levon 		return;
6321f5207b7SJohn Levon 	}
6331f5207b7SJohn Levon 	sym->namespace = ns;
6341f5207b7SJohn Levon 	sym->next_id = ident->symbols;
6351f5207b7SJohn Levon 	ident->symbols = sym;
6361f5207b7SJohn Levon 	if (sym->ident && sym->ident != ident)
6371f5207b7SJohn Levon 		warning(sym->pos, "Symbol '%s' already bound", show_ident(sym->ident));
6381f5207b7SJohn Levon 	sym->ident = ident;
6391f5207b7SJohn Levon 	sym->bound = 1;
6401f5207b7SJohn Levon 
6411f5207b7SJohn Levon 	scope = block_scope;
6421f5207b7SJohn Levon 	if (ns == NS_SYMBOL && toplevel(scope)) {
6431f5207b7SJohn Levon 		unsigned mod = MOD_ADDRESSABLE | MOD_TOPLEVEL;
6441f5207b7SJohn Levon 
6451f5207b7SJohn Levon 		scope = global_scope;
6461f5207b7SJohn Levon 		if (sym->ctype.modifiers & MOD_STATIC ||
6471f5207b7SJohn Levon 		    is_extern_inline(sym)) {
6481f5207b7SJohn Levon 			scope = file_scope;
6491f5207b7SJohn Levon 			mod = MOD_TOPLEVEL;
6501f5207b7SJohn Levon 		}
6511f5207b7SJohn Levon 		sym->ctype.modifiers |= mod;
6521f5207b7SJohn Levon 	}
6531f5207b7SJohn Levon 	if (ns == NS_MACRO)
6541f5207b7SJohn Levon 		scope = file_scope;
6551f5207b7SJohn Levon 	if (ns == NS_LABEL)
6561f5207b7SJohn Levon 		scope = function_scope;
6571f5207b7SJohn Levon 	bind_scope(sym, scope);
6581f5207b7SJohn Levon }
6591f5207b7SJohn Levon 
create_symbol(int stream,const char * name,int type,int namespace)6601f5207b7SJohn Levon struct symbol *create_symbol(int stream, const char *name, int type, int namespace)
6611f5207b7SJohn Levon {
6621f5207b7SJohn Levon 	struct ident *ident = built_in_ident(name);
6631f5207b7SJohn Levon 	struct symbol *sym = lookup_symbol(ident, namespace);
6641f5207b7SJohn Levon 
6651f5207b7SJohn Levon 	if (sym && sym->type != type)
6661f5207b7SJohn Levon 		die("symbol %s created with different types: %d old %d", name,
6671f5207b7SJohn Levon 				type, sym->type);
6681f5207b7SJohn Levon 
6691f5207b7SJohn Levon 	if (!sym) {
6701f5207b7SJohn Levon 		struct token *token = built_in_token(stream, ident);
6711f5207b7SJohn Levon 
6721f5207b7SJohn Levon 		sym = alloc_symbol(token->pos, type);
6731f5207b7SJohn Levon 		bind_symbol(sym, token->ident, namespace);
6741f5207b7SJohn Levon 	}
6751f5207b7SJohn Levon 	return sym;
6761f5207b7SJohn Levon }
6771f5207b7SJohn Levon 
6781f5207b7SJohn Levon 
6791f5207b7SJohn Levon /*
6801f5207b7SJohn Levon  * Abstract types
6811f5207b7SJohn Levon  */
6821f5207b7SJohn Levon struct symbol	int_type,
6831f5207b7SJohn Levon 		fp_type;
6841f5207b7SJohn Levon 
6851f5207b7SJohn Levon /*
6861f5207b7SJohn Levon  * C types (i.e. actual instances that the abstract types
6871f5207b7SJohn Levon  * can map onto)
6881f5207b7SJohn Levon  */
6891f5207b7SJohn Levon struct symbol	bool_ctype, void_ctype, type_ctype,
6901f5207b7SJohn Levon 		char_ctype, schar_ctype, uchar_ctype,
6911f5207b7SJohn Levon 		short_ctype, sshort_ctype, ushort_ctype,
6921f5207b7SJohn Levon 		int_ctype, sint_ctype, uint_ctype,
6931f5207b7SJohn Levon 		long_ctype, slong_ctype, ulong_ctype,
6941f5207b7SJohn Levon 		llong_ctype, sllong_ctype, ullong_ctype,
6951f5207b7SJohn Levon 		lllong_ctype, slllong_ctype, ulllong_ctype,
6961f5207b7SJohn Levon 		float_ctype, double_ctype, ldouble_ctype,
6971f5207b7SJohn Levon 		string_ctype, ptr_ctype, lazy_ptr_ctype,
6981f5207b7SJohn Levon 		incomplete_ctype, label_ctype, bad_ctype,
6991f5207b7SJohn Levon 		null_ctype;
700*c85f09ccSJohn Levon struct symbol	int_ptr_ctype, uint_ptr_ctype;
701*c85f09ccSJohn Levon struct symbol	long_ptr_ctype, ulong_ptr_ctype;
702*c85f09ccSJohn Levon struct symbol	llong_ptr_ctype, ullong_ptr_ctype;
703*c85f09ccSJohn Levon struct symbol	float32_ctype, float32x_ctype;
704*c85f09ccSJohn Levon struct symbol	float64_ctype, float64x_ctype;
705*c85f09ccSJohn Levon struct symbol	float128_ctype;
706*c85f09ccSJohn Levon struct symbol	const_void_ctype, const_char_ctype;
707*c85f09ccSJohn Levon struct symbol	const_ptr_ctype, const_string_ctype;
7081f5207b7SJohn Levon 
7091f5207b7SJohn Levon struct symbol	zero_int;
7101f5207b7SJohn Levon 
7111f5207b7SJohn Levon #define __INIT_IDENT(str, res) { .len = sizeof(str)-1, .name = str, .reserved = res }
7121f5207b7SJohn Levon #define __IDENT(n,str,res) \
7131f5207b7SJohn Levon 	struct ident n  = __INIT_IDENT(str,res)
7141f5207b7SJohn Levon 
7151f5207b7SJohn Levon #include "ident-list.h"
7161f5207b7SJohn Levon 
init_symbols(void)7171f5207b7SJohn Levon void init_symbols(void)
7181f5207b7SJohn Levon {
7191f5207b7SJohn Levon 	int stream = init_stream("builtin", -1, includepath);
7201f5207b7SJohn Levon 
7211f5207b7SJohn Levon #define __IDENT(n,str,res) \
7221f5207b7SJohn Levon 	hash_ident(&n)
7231f5207b7SJohn Levon #include "ident-list.h"
7241f5207b7SJohn Levon 
7251f5207b7SJohn Levon 	init_parser(stream);
7261f5207b7SJohn Levon 	init_builtins(stream);
7271f5207b7SJohn Levon }
7281f5207b7SJohn Levon 
7291f5207b7SJohn Levon #ifdef __CHAR_UNSIGNED__
7301f5207b7SJohn Levon #define CHAR_SIGNEDNESS MOD_UNSIGNED
7311f5207b7SJohn Levon #else
7321f5207b7SJohn Levon #define CHAR_SIGNEDNESS MOD_SIGNED
7331f5207b7SJohn Levon #endif
734*c85f09ccSJohn Levon // For fix-sized types
735*c85f09ccSJohn Levon static int bits_in_type32 = 32;
736*c85f09ccSJohn Levon static int bits_in_type64 = 64;
737*c85f09ccSJohn Levon static int bits_in_type128 = 128;
7381f5207b7SJohn Levon 
7391f5207b7SJohn Levon #define MOD_ESIGNED (MOD_SIGNED | MOD_EXPLICITLY_SIGNED)
7401f5207b7SJohn Levon #define MOD_LL (MOD_LONG | MOD_LONGLONG)
7411f5207b7SJohn Levon #define MOD_LLL MOD_LONGLONGLONG
7421f5207b7SJohn Levon static const struct ctype_declare {
7431f5207b7SJohn Levon 	struct symbol *ptr;
7441f5207b7SJohn Levon 	enum type type;
7451f5207b7SJohn Levon 	unsigned long modifiers;
7461f5207b7SJohn Levon 	int *bit_size;
7471f5207b7SJohn Levon 	int *maxalign;
7481f5207b7SJohn Levon 	struct symbol *base_type;
7491f5207b7SJohn Levon } ctype_declaration[] = {
7501f5207b7SJohn Levon 	{ &bool_ctype,	    SYM_BASETYPE, MOD_UNSIGNED,		    &bits_in_bool,	     &max_int_alignment, &int_type },
7511f5207b7SJohn Levon 	{ &void_ctype,	    SYM_BASETYPE, 0,			    NULL,	     NULL,		 NULL },
7521f5207b7SJohn Levon 	{ &type_ctype,	    SYM_BASETYPE, MOD_TYPE,		    NULL,		     NULL,		 NULL },
7531f5207b7SJohn Levon 	{ &incomplete_ctype,SYM_BASETYPE, 0,			    NULL,		     NULL,		 NULL },
7541f5207b7SJohn Levon 	{ &bad_ctype,	    SYM_BASETYPE, 0,			    NULL,		     NULL,		 NULL },
7551f5207b7SJohn Levon 
7561f5207b7SJohn Levon 	{ &char_ctype,	    SYM_BASETYPE, CHAR_SIGNEDNESS | MOD_CHAR,    &bits_in_char,	     &max_int_alignment, &int_type },
7571f5207b7SJohn Levon 	{ &schar_ctype,	    SYM_BASETYPE, MOD_ESIGNED | MOD_CHAR,   &bits_in_char,	     &max_int_alignment, &int_type },
7581f5207b7SJohn Levon 	{ &uchar_ctype,	    SYM_BASETYPE, MOD_UNSIGNED | MOD_CHAR,  &bits_in_char,	     &max_int_alignment, &int_type },
7591f5207b7SJohn Levon 	{ &short_ctype,	    SYM_BASETYPE, MOD_SIGNED | MOD_SHORT,   &bits_in_short,	     &max_int_alignment, &int_type },
7601f5207b7SJohn Levon 	{ &sshort_ctype,    SYM_BASETYPE, MOD_ESIGNED | MOD_SHORT,  &bits_in_short,	     &max_int_alignment, &int_type },
7611f5207b7SJohn Levon 	{ &ushort_ctype,    SYM_BASETYPE, MOD_UNSIGNED | MOD_SHORT, &bits_in_short,	     &max_int_alignment, &int_type },
7621f5207b7SJohn Levon 	{ &int_ctype,	    SYM_BASETYPE, MOD_SIGNED,		    &bits_in_int,	     &max_int_alignment, &int_type },
7631f5207b7SJohn Levon 	{ &sint_ctype,	    SYM_BASETYPE, MOD_ESIGNED,		    &bits_in_int,	     &max_int_alignment, &int_type },
7641f5207b7SJohn Levon 	{ &uint_ctype,	    SYM_BASETYPE, MOD_UNSIGNED,		    &bits_in_int,	     &max_int_alignment, &int_type },
7651f5207b7SJohn Levon 	{ &long_ctype,	    SYM_BASETYPE, MOD_SIGNED | MOD_LONG,    &bits_in_long,	     &max_int_alignment, &int_type },
7661f5207b7SJohn Levon 	{ &slong_ctype,	    SYM_BASETYPE, MOD_ESIGNED | MOD_LONG,   &bits_in_long,	     &max_int_alignment, &int_type },
7671f5207b7SJohn Levon 	{ &ulong_ctype,	    SYM_BASETYPE, MOD_UNSIGNED | MOD_LONG,  &bits_in_long,	     &max_int_alignment, &int_type },
7681f5207b7SJohn Levon 	{ &llong_ctype,	    SYM_BASETYPE, MOD_SIGNED | MOD_LL,	    &bits_in_longlong,       &max_int_alignment, &int_type },
7691f5207b7SJohn Levon 	{ &sllong_ctype,    SYM_BASETYPE, MOD_ESIGNED | MOD_LL,	    &bits_in_longlong,       &max_int_alignment, &int_type },
7701f5207b7SJohn Levon 	{ &ullong_ctype,    SYM_BASETYPE, MOD_UNSIGNED | MOD_LL,    &bits_in_longlong,       &max_int_alignment, &int_type },
7711f5207b7SJohn Levon 	{ &lllong_ctype,    SYM_BASETYPE, MOD_SIGNED | MOD_LLL,	    &bits_in_longlonglong,   &max_int_alignment, &int_type },
7721f5207b7SJohn Levon 	{ &slllong_ctype,   SYM_BASETYPE, MOD_ESIGNED | MOD_LLL,    &bits_in_longlonglong,   &max_int_alignment, &int_type },
7731f5207b7SJohn Levon 	{ &ulllong_ctype,   SYM_BASETYPE, MOD_UNSIGNED | MOD_LLL,   &bits_in_longlonglong,   &max_int_alignment, &int_type },
7741f5207b7SJohn Levon 
7751f5207b7SJohn Levon 	{ &float_ctype,	    SYM_BASETYPE,  0,			    &bits_in_float,          &max_fp_alignment,  &fp_type },
7761f5207b7SJohn Levon 	{ &double_ctype,    SYM_BASETYPE, MOD_LONG,		    &bits_in_double,         &max_fp_alignment,  &fp_type },
7771f5207b7SJohn Levon 	{ &ldouble_ctype,   SYM_BASETYPE, MOD_LONG | MOD_LONGLONG,  &bits_in_longdouble,     &max_fp_alignment,  &fp_type },
7781f5207b7SJohn Levon 
779*c85f09ccSJohn Levon 	{ &float32_ctype,   SYM_BASETYPE,  0,			    &bits_in_type32,          &max_fp_alignment, &fp_type },
780*c85f09ccSJohn Levon 	{ &float32x_ctype,  SYM_BASETYPE, MOD_LONG,		    &bits_in_double,         &max_fp_alignment,  &fp_type },
781*c85f09ccSJohn Levon 	{ &float64_ctype,   SYM_BASETYPE,  0,			    &bits_in_type64,          &max_fp_alignment, &fp_type },
782*c85f09ccSJohn Levon 	{ &float64x_ctype,  SYM_BASETYPE, MOD_LONG | MOD_LONGLONG,  &bits_in_longdouble,     &max_fp_alignment,  &fp_type },
783*c85f09ccSJohn Levon 	{ &float128_ctype,  SYM_BASETYPE,  0,			    &bits_in_type128,         &max_alignment,    &fp_type },
784*c85f09ccSJohn Levon 
7851f5207b7SJohn Levon 	{ &string_ctype,    SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &char_ctype },
7861f5207b7SJohn Levon 	{ &ptr_ctype,	    SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &void_ctype },
7871f5207b7SJohn Levon 	{ &null_ctype,	    SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &void_ctype },
7881f5207b7SJohn Levon 	{ &label_ctype,	    SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &void_ctype },
7891f5207b7SJohn Levon 	{ &lazy_ptr_ctype,  SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &void_ctype },
790*c85f09ccSJohn Levon 	{ &int_ptr_ctype,   SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &int_ctype },
791*c85f09ccSJohn Levon 	{ &uint_ptr_ctype,  SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &uint_ctype },
792*c85f09ccSJohn Levon 	{ &long_ptr_ctype,  SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &long_ctype },
793*c85f09ccSJohn Levon 	{ &ulong_ptr_ctype, SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &ulong_ctype },
794*c85f09ccSJohn Levon 	{ &llong_ptr_ctype, SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &llong_ctype },
795*c85f09ccSJohn Levon 	{ &ullong_ptr_ctype,SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &ullong_ctype },
796*c85f09ccSJohn Levon 
797*c85f09ccSJohn Levon 	{ &const_void_ctype, SYM_NODE,	  MOD_CONST,		    NULL, NULL, &void_ctype },
798*c85f09ccSJohn Levon 	{ &const_char_ctype, SYM_NODE,	  MOD_CONST,		    &bits_in_char, &max_int_alignment, &char_ctype },
799*c85f09ccSJohn Levon 	{ &const_ptr_ctype, SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &const_void_ctype },
800*c85f09ccSJohn Levon 	{ &const_string_ctype,SYM_PTR,	  0,			    &bits_in_pointer,        &pointer_alignment, &const_char_ctype },
8011f5207b7SJohn Levon 	{ NULL, }
8021f5207b7SJohn Levon };
8031f5207b7SJohn Levon #undef MOD_LLL
8041f5207b7SJohn Levon #undef MOD_LL
8051f5207b7SJohn Levon #undef MOD_ESIGNED
8061f5207b7SJohn Levon 
init_ctype(void)8071f5207b7SJohn Levon void init_ctype(void)
8081f5207b7SJohn Levon {
8091f5207b7SJohn Levon 	const struct ctype_declare *ctype;
8101f5207b7SJohn Levon 
8111f5207b7SJohn Levon 	for (ctype = ctype_declaration ; ctype->ptr; ctype++) {
8121f5207b7SJohn Levon 		struct symbol *sym = ctype->ptr;
8131f5207b7SJohn Levon 		unsigned long bit_size = ctype->bit_size ? *ctype->bit_size : -1;
8141f5207b7SJohn Levon 		unsigned long maxalign = ctype->maxalign ? *ctype->maxalign : 0;
8151f5207b7SJohn Levon 		unsigned long alignment = bits_to_bytes(bit_size);
8161f5207b7SJohn Levon 
8171f5207b7SJohn Levon 		if (alignment > maxalign)
8181f5207b7SJohn Levon 			alignment = maxalign;
8191f5207b7SJohn Levon 		sym->type = ctype->type;
8201f5207b7SJohn Levon 		sym->bit_size = bit_size;
8211f5207b7SJohn Levon 		sym->ctype.alignment = alignment;
8221f5207b7SJohn Levon 		sym->ctype.base_type = ctype->base_type;
8231f5207b7SJohn Levon 		sym->ctype.modifiers = ctype->modifiers;
8241f5207b7SJohn Levon 	}
825*c85f09ccSJohn Levon 
826*c85f09ccSJohn Levon 	// and now some adjustments
827*c85f09ccSJohn Levon 	if (funsigned_char) {
828*c85f09ccSJohn Levon 		char_ctype.ctype.modifiers |= MOD_UNSIGNED;
829*c85f09ccSJohn Levon 		char_ctype.ctype.modifiers &= ~MOD_SIGNED;
830*c85f09ccSJohn Levon 	}
8311f5207b7SJohn Levon }
832