-static void parse_microsoft_based(based_spec_t *based_spec)
-{
- if (token.type != T_IDENTIFIER) {
- parse_error_expected("while parsing __based", T_IDENTIFIER, NULL);
- return;
- }
- symbol_t *symbol = token.v.symbol;
- entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL);
-
- if (entity == NULL || entity->base.kind != ENTITY_VARIABLE) {
- errorf(HERE, "'%Y' is not a variable name.", symbol);
- entity = create_error_entity(symbol, ENTITY_VARIABLE);
- } else {
- variable_t *variable = &entity->variable;
-
- if (based_spec->base_variable != NULL) {
- errorf(HERE, "__based type qualifier specified more than once");
- }
- based_spec->source_position = token.source_position;
- based_spec->base_variable = variable;
-
- type_t *const type = variable->base.type;
-
- if (is_type_valid(type)) {
- if (! is_type_pointer(skip_typeref(type))) {
- errorf(HERE, "variable in __based modifier must have pointer type instead of '%T'", type);
- }
- if (variable->base.base.parent_scope != file_scope) {
- errorf(HERE, "a nonstatic local variable may not be used in a __based specification");
- }
- }
- }
- next_token();
-}
-
-/**
- * Finish the construction of a struct type by calculating
- * its size, offsets, alignment.
- */
-static void finish_struct_type(compound_type_t *type)
-{
- assert(type->compound != NULL);
-
- compound_t *compound = type->compound;
- if (!compound->complete)
- return;
-
- il_size_t size = 0;
- il_size_t offset;
- il_alignment_t alignment = 1;
- bool need_pad = false;
-
- entity_t *entry = compound->members.entities;
- for (; entry != NULL; entry = entry->base.next) {
- if (entry->kind != ENTITY_COMPOUND_MEMBER)
- continue;
-
- type_t *m_type = skip_typeref(entry->declaration.type);
- if (! is_type_valid(m_type)) {
- /* simply ignore errors here */
- continue;
- }
- il_alignment_t m_alignment = m_type->base.alignment;
- if (m_alignment > alignment)
- alignment = m_alignment;
-
- offset = (size + m_alignment - 1) & -m_alignment;
-
- if (offset > size)
- need_pad = true;
- entry->compound_member.offset = offset;
- size = offset + m_type->base.size;
- }
- if (type->base.alignment != 0) {
- alignment = type->base.alignment;
- }
-
- offset = (size + alignment - 1) & -alignment;
- if (offset > size)
- need_pad = true;
-
- if (need_pad) {
- if (warning.padded) {
- warningf(&compound->base.source_position, "'%T' needs padding", type);
- }
- } else {
- if (compound->modifiers & DM_PACKED && warning.packed) {
- warningf(&compound->base.source_position,
- "superfluous packed attribute on '%T'", type);
- }
- }
-
- type->base.size = offset;
- type->base.alignment = alignment;
-}
-
-/**
- * Finish the construction of an union type by calculating
- * its size and alignment.
- */
-static void finish_union_type(compound_type_t *type)
-{
- assert(type->compound != NULL);
-
- compound_t *compound = type->compound;
- if (! compound->complete)
- return;
-
- il_size_t size = 0;
- il_alignment_t alignment = 1;
-
- entity_t *entry = compound->members.entities;
- for (; entry != NULL; entry = entry->base.next) {
- if (entry->kind != ENTITY_COMPOUND_MEMBER)
- continue;
-
- type_t *m_type = skip_typeref(entry->declaration.type);
- if (! is_type_valid(m_type))
- continue;
-
- entry->compound_member.offset = 0;
- if (m_type->base.size > size)
- size = m_type->base.size;
- if (m_type->base.alignment > alignment)
- alignment = m_type->base.alignment;
- }
- if (type->base.alignment != 0) {
- alignment = type->base.alignment;
- }
- size = (size + alignment - 1) & -alignment;
- type->base.size = size;
- type->base.alignment = alignment;
-}
-
-static type_t *handle_attribute_mode(const gnu_attribute_t *attribute,
- type_t *orig_type)
-{
- type_t *type = skip_typeref(orig_type);
-
- /* at least: byte, word, pointer, list of machine modes
- * __XXX___ is interpreted as XXX */
-
- /* This isn't really correct, the backend should provide a list of machine
- * specific modes (according to gcc philosophy that is...) */
- const char *symbol_str = attribute->u.symbol->string;
- bool sign = is_type_signed(type);
- atomic_type_kind_t akind;
- if (strcmp_underscore("QI", symbol_str) == 0 ||
- strcmp_underscore("byte", symbol_str) == 0) {
- akind = sign ? ATOMIC_TYPE_CHAR : ATOMIC_TYPE_UCHAR;
- } else if (strcmp_underscore("HI", symbol_str) == 0) {
- akind = sign ? ATOMIC_TYPE_SHORT : ATOMIC_TYPE_USHORT;
- } else if (strcmp_underscore("SI", symbol_str) == 0
- || strcmp_underscore("word", symbol_str) == 0
- || strcmp_underscore("pointer", symbol_str) == 0) {
- akind = sign ? ATOMIC_TYPE_INT : ATOMIC_TYPE_UINT;
- } else if (strcmp_underscore("DI", symbol_str) == 0) {
- akind = sign ? ATOMIC_TYPE_LONGLONG : ATOMIC_TYPE_ULONGLONG;
- } else {
- if (warning.other)
- warningf(HERE, "ignoring unknown mode '%s'", symbol_str);
- return orig_type;
- }
-
- if (type->kind == TYPE_ATOMIC) {
- type_t *copy = duplicate_type(type);
- copy->atomic.akind = akind;
- return identify_new_type(copy);
- } else if (type->kind == TYPE_ENUM) {
- type_t *copy = duplicate_type(type);
- copy->enumt.akind = akind;
- return identify_new_type(copy);
- } else if (is_type_pointer(type)) {
- warningf(HERE, "__attribute__((mode)) on pointers not implemented yet (ignored)");
- return type;
- }
-
- errorf(HERE, "__attribute__((mode)) only allowed on integer, enum or pointer type");
- return orig_type;
-}
-
-static type_t *handle_type_attributes(const gnu_attribute_t *attributes,
- type_t *type)
-{
- const gnu_attribute_t *attribute = attributes;
- for ( ; attribute != NULL; attribute = attribute->next) {
- if (attribute->invalid)
- continue;
-
- if (attribute->kind == GNU_AK_MODE) {
- type = handle_attribute_mode(attribute, type);
- } else if (attribute->kind == GNU_AK_ALIGNED) {
- int alignment = 32; /* TODO: fill in maximum useful alignment for
- target machine */
- if (attribute->has_arguments)
- alignment = attribute->u.argument;
-
- type_t *copy = duplicate_type(type);
- copy->base.alignment = attribute->u.argument;
- type = identify_new_type(copy);
- }
- }
-
- return type;
-}
-