/** * Part of the Lccrt Project, under the Apache License v2.0 * See http://www.apache.org/licenses/LICENSE-2.0.txt for license information. * SPDX-License-Identifier: Apache-2.0 * * lccrt_type.c - реализация пользовательский интерфейс (динамической) компиляции. */ #include #include #include #include #include #include #include #include #include "lccrt_real.h" #define LCCRT_TYPE_ALIGN( size, align) ((align)*(((size) + (align) - 1) / (align))) /** * Оценка количества десятичных цифр для неотрицательного значения. */ #define lccrt_calc_num_digits( v) \ ( ((v) & 0xff000000) \ ? 12 \ : (((v) & 0x00ff0000) \ ? 9 \ : (((v) & 0x0000ff00) ? 6 : 3)) ) #define lccrt_is_char_shielded( c) \ ( (c == '@') \ || (c == '.') \ || (c == '\\') ) /** * Вычислить длину строки вместе с символами экранирования. */ static int lccrt_calc_name_shield( const char *name) { int k; int r = 0; for ( k = 0; name[k]; ++k, ++r ) { char c = name[k]; if ( (c == '\\') && name[k+1] && lccrt_is_char_shielded( name[k+1]) ) { ++k; ++r; } else if ( lccrt_is_char_shielded( c) ) { ++r; } } return (r); } /* lccrt_calc_name_shield */ /** * Печать строки с экранированием. */ static int lccrt_print_shield_name( char *dst, int max_len, const char *name) { int k; int r = 0; for ( k = 0; name[k] && (r <= max_len); ++k, ++r ) { char c = name[k]; if ( (c == '\\') && name[k+1] && lccrt_is_char_shielded( name[k+1]) ) { dst[r+0] = c; c = name[k+1]; ++k; ++r; } else if ( lccrt_is_char_shielded( c) ) { dst[r] = '\\'; ++r; } dst[r] = c; } dst[r] = 0; return (r); } /* lccrt_print_shield_name */ /** * Создание нового типа. */ lccrt_type_ptr lccrt_type_make( lccrt_module_ptr m, int type_name, lccrt_type_ptr parent, lccrt_type_ptr *args, uint64_t num_args, lccrt_var_ptr vnum, const char *sym_name, int is_sign, uint64_t bytealign, uint64_t bytesize, uint64_t byteshift, int bitsubshift, int bitsubsize, int is_union) { int k; lccrt_type_ptr r; lccrt_he_ptr e; lccrt_context_ptr ctx = m->ctx; lccrt_check_type_assert( m, lccrt_module_t); lccrt_check_type_assert( parent, lccrt_type_t); if ( (type_name != LCCRT_TYPE_ARRAY) && (type_name != LCCRT_TYPE_VECTOR) ) { for ( k = 0; k < num_args; ++k ) { lccrt_check_type_assert( args[k], lccrt_type_t); } } if ( parent && (parent->type_name == LCCRT_TYPE_NAME) ) { if ( (type_name != LCCRT_TYPE_PTR) && (type_name != LCCRT_TYPE_FIELD) && (type_name != LCCRT_TYPE_FUNC) && (type_name != LCCRT_TYPE_ARRAY) ) { lccrt_assert( 0); return (0); } } #if 0 if ( (type_name == LCCRT_TYPE_PTR) ) { if ( (parent->type_name == LCCRT_TYPE_STRUCT) ) { lccrt_assert( 0); return (0); } } #endif e = lccrt_hash_find( m->types, (uintptr_t)sym_name); r = e ? (lccrt_type_ptr)lccrt_hash_get( e) : 0; if ( r ) { lccrt_check_type_assert( r, lccrt_type_t); lccrt_assert( r->type_name == type_name); lccrt_assert( r->num_args == num_args); lccrt_assert( r->vnum == vnum); lccrt_assert( strcmp( r->sym_name, sym_name) == 0); lccrt_assert( r->is_sign == is_sign); if ( (r->type_name == LCCRT_TYPE_NAME) ) { if ( parent ) { lccrt_assert( (r->bytealign == parent->bytealign) || (r->bytealign == 0)); lccrt_assert( (r->bytesize == parent->bytesize) || (r->bytesize == 0)); } else { lccrt_assert( (r->bytealign == bytealign) || (bytealign == 0)); lccrt_assert( (r->bytesize == bytesize) || (bytesize == 0)); } } else { lccrt_assert( r->bytealign == bytealign); lccrt_assert( r->bytesize == bytesize); } lccrt_assert( r->byteshift == byteshift); if ( (r->type_name == LCCRT_TYPE_FIELD) && (r->parent->type_name == LCCRT_TYPE_INT) ) { lccrt_assert( r->bitsubshift == bitsubshift); lccrt_assert( r->bitsubsize == bitsubsize); } lccrt_assert( r->is_union == is_union); for ( k = 0; k < num_args; ++k ) { if ( (type_name != LCCRT_TYPE_ARRAY) && (type_name != LCCRT_TYPE_VECTOR) ) { lccrt_assert( (args[0] == 0) || (r->args[k] == args[k])); } } if ( (r->type_name == LCCRT_TYPE_NAME) ) { if ( r->parent ) { lccrt_assert( (parent == 0) || r->parent == (lccrt_type_ptr)parent); } else { r->parent = parent; } } else { lccrt_assert( (parent == 0) || (r->parent == parent)); } } else { int is_fld = (type_name == LCCRT_TYPE_FIELD); int is_fld_int = is_fld && (!parent || (parent->type_name == LCCRT_TYPE_INT)); r = lccrt_ctx_malloc( ctx, lccrt_type_t); memset( r, 0, sizeof( r[0])); lccrt_check_type_init( r, lccrt_type_t); lccrt_ilist_unit_init( &(r->types_unit)); r->m = m; m->type_max++; r->ident_num = m->type_max; r->type_name = type_name; r->parent = (lccrt_type_ptr)parent; r->num_args = num_args; r->vnum = vnum; r->sym_name = sym_name ? lccrt_ctx_copy_str( ctx, sym_name) : 0; r->is_sign = is_sign; r->bytealign = bytealign; r->bytesize = bytesize; r->byteshift = byteshift; r->bitsubshift = is_fld_int ? bitsubshift : 0; r->bitsubsize = is_fld_int ? bitsubsize : 0; r->is_union = is_union; r->args = 0; if ( num_args && (type_name != LCCRT_TYPE_ARRAY) && (type_name != LCCRT_TYPE_VECTOR) ) { r->args = lccrt_ctx_mallocn( ctx, lccrt_type_ptr, num_args); memcpy( r->args, args, num_args * sizeof( args[0])); } e = lccrt_hash_push( m->types, (uintptr_t)r->sym_name, 0); lccrt_hash_set( e, (uintptr_t)r); lccrt_ilist_head_insert( &(m->types_head), types_unit, r); } return (r); } /* lccrt_type_make */ /** * Удаление типа данных. */ void lccrt_type_delete( lccrt_type_ptr type) { lccrt_module_ptr m = type->m; lccrt_context_ptr ctx = m->ctx; lccrt_check_type_assert( type, lccrt_type_t); lccrt_ilist_head_remove( &(m->types_head), types_unit, type); lccrt_ctx_free( ctx, type->sym_name); lccrt_ctx_free( ctx, type->args); lccrt_check_type_done( type, lccrt_type_t); lccrt_ctx_free( ctx, type); return; } /* lccrt_type_delete */ /** * Получить значение поля. */ lccrt_type_ptr lccrt_type_get_next_type( lccrt_type_ptr type) { lccrt_type_ptr r; lccrt_check_type_assert( type, lccrt_type_t); r = type->types_unit.next; return (r); } /* lccrt_type_get_next_type */ /** * Создание нового простого типа. */ lccrt_type_ptr lccrt_type_make_simple( lccrt_m_ptr m, lccrt_type_name_t name, const char *sym_name, int is_sign, uint64_t bytealign, uint64_t bytesize) { lccrt_type_ptr r; r = lccrt_type_make( m, name, 0, 0, 0, 0, sym_name, is_sign, bytealign, bytesize, 0, 0, 0, 0); return (r); } /* lccrt_type_make_simple */ /** * Получить целый тип. */ lccrt_type_ptr lccrt_type_make_int( lccrt_module_ptr m, uint64_t bytesize, int is_sign) { lccrt_type_ptr r; lccrt_type_name_int_t k = lccrt_type_int_find_by_bitsize( 8*bytesize); lccrt_check_type_assert( m, lccrt_module_t); r = m->types_std.int_types[is_sign][k]; return (r); } /* lccrt_type_make_int */ /** * Создание типа указателя (с частичным "хешированием"). */ lccrt_type_ptr lccrt_type_make_ptr_type( lccrt_type_ptr type) { lccrt_type_ptr r = 0; char s[64]; lccrt_module_ptr m = type->m; lccrt_check_type_assert( type, lccrt_type_t); lccrt_check_type_assert( m, lccrt_module_t); if ( m->types_std.ptr_byte && (type == lccrt_type_make_int( m, 1, 0)) ) { r = m->types_std.ptr_byte; } else if ( m->types_std.ptr_char && (type == lccrt_type_make_int( m, 1, 1)) ) { r = m->types_std.ptr_char; } else if ( m->types_std.ptr_intptr && (type == m->types_std.intptr) ) { r = m->types_std.ptr_intptr; } else { uint64_t bytesize = m->types_std.ptr_bytesize; snprintf( s, 64, "*$%ju", type->ident_num); r = lccrt_type_make( m, LCCRT_TYPE_PTR, type, 0, 0, 0, s, 0, bytesize, bytesize, 0, 0, 0, 0); } return (r); } /* lccrt_type_make_ptr_type */ /** * Получить void-тип. */ lccrt_type_ptr lccrt_type_make_void( lccrt_module_ptr m) { lccrt_type_ptr r = m->types_std.void_type; lccrt_check_type_assert( m, lccrt_module_t); return (r); } /* lccrt_type_make_void */ /** * Получить bool-тип. */ lccrt_type_ptr lccrt_type_make_bool( lccrt_module_ptr m) { lccrt_type_ptr r = m->types_std.bool_type; lccrt_check_type_assert( m, lccrt_module_t); return (r); } /* lccrt_type_make_bool */ /** * Получить тип-многоточие. */ lccrt_type_ptr lccrt_type_make_ellipsis( lccrt_module_ptr m) { lccrt_type_ptr r = m->types_std.ellipsis; lccrt_check_type_assert( m, lccrt_module_t); return (r); } /* lccrt_type_make_ellipsis */ /** * Получить плавающий тип. */ lccrt_type_ptr lccrt_type_make_float( lccrt_module_ptr m, uint64_t bytesize) { lccrt_type_name_float_t k = lccrt_type_float_find_by_bitsize( 8*bytesize); lccrt_type_ptr r = m->types_std.float_types[k]; lccrt_check_type_assert( m, lccrt_module_t); return (r); } /* lccrt_type_make_float */ /** * Получить целый тип. */ lccrt_type_ptr lccrt_type_make_intptr( lccrt_module_ptr m) { lccrt_type_ptr r = m->types_std.intptr; lccrt_check_type_assert( m, lccrt_module_t); return (r); } /* lccrt_type_make_intptr */ /** * Получить указатель на целый тип. */ lccrt_type_ptr lccrt_type_make_pintptr( lccrt_module_ptr m) { lccrt_type_ptr r = m->types_std.ptr_intptr; lccrt_check_type_assert( m, lccrt_module_t); return (r); } /* lccrt_type_make_pintptr */ /** * Получить указатель на беззнаковый байт. */ lccrt_type_ptr lccrt_type_make_pbyte( lccrt_module_ptr m) { lccrt_type_ptr r = m->types_std.ptr_byte; lccrt_check_type_assert( m, lccrt_module_t); return (r); } /* lccrt_type_make_pbyte */ /** * Получить указатель на знаковый байт. */ lccrt_type_ptr lccrt_type_make_pchar( lccrt_module_ptr m) { lccrt_type_ptr r = m->types_std.ptr_char; lccrt_check_type_assert( m, lccrt_module_t); return (r); } /* lccrt_type_make_pchar */ /** * Получить указатель на void. */ lccrt_type_ptr lccrt_type_make_pvoid( lccrt_module_ptr m) { lccrt_type_ptr r = lccrt_type_make_ptr_type( m->types_std.void_type); return (r); } /* lccrt_type_make_pvoid */ /** * Получить тип - массив. */ lccrt_type_ptr lccrt_type_make_array( lccrt_type_ptr elem, uint64_t num_elems) { lccrt_type_ptr r; char s[64]; lccrt_module_ptr m = elem->m; uint64_t elem_bytesize = lccrt_type_get_bytesize( elem); uint64_t elem_bytealign = lccrt_type_get_bytealign( elem); uint64_t bytesize = num_elems * LCCRT_TYPE_ALIGN( elem_bytesize, elem_bytealign); lccrt_check_type_assert( elem, lccrt_type_t); snprintf( s, 64, "[%ju]$%ju", num_elems, elem->ident_num); r = lccrt_type_make( m, LCCRT_TYPE_ARRAY, elem, 0, num_elems, 0, s, 0, elem_bytealign, bytesize, 0, 0, 0, 0); return (r); } /* lccrt_type_make_array */ /** * Получить тип - вектор. */ lccrt_type_ptr lccrt_type_make_vector( lccrt_type_ptr elem, uint64_t num_elems) { lccrt_type_ptr r; char s[64]; lccrt_module_ptr m = elem->m; uint64_t elem_bytesize = lccrt_type_get_bytesize( elem); uint64_t elem_bytealign = lccrt_type_get_bytealign( elem); uint64_t bytesize = num_elems * LCCRT_TYPE_ALIGN( elem_bytesize, elem_bytealign); lccrt_check_type_assert( elem, lccrt_type_t); snprintf( s, 64, "<%ju>$%ju", num_elems, elem->ident_num); r = lccrt_type_make( m, LCCRT_TYPE_VECTOR, elem, 0, num_elems, 0, s, 0, elem_bytealign, bytesize, 0, 0, 0, 0); return (r); } /* lccrt_type_make_vector */ /** * Получить тип - vla-массив. */ lccrt_type_ptr lccrt_type_make_vla( lccrt_type_ptr elem, lccrt_var_ptr vnum) { lccrt_type_ptr r; char s[64]; lccrt_module_ptr m = elem->m; uint64_t bytealign = lccrt_type_get_bytealign( elem); lccrt_check_type_assert( elem, lccrt_type_t); snprintf( s, 64, "[@%s]$%ju", vnum->name, elem->ident_num); r = lccrt_type_make( m, LCCRT_TYPE_VLA_ARRAY, elem, 0, 0, vnum, s, 0, bytealign, 0, 0, 0, 0, 0); return (r); } /* lccrt_type_make_vla */ /** * Получить тип - поле структуры. */ lccrt_type_ptr lccrt_type_make_field( lccrt_type_ptr parent, uint64_t bytealign, uint64_t byteshift, int bitsubshift, int bitsubsize) { lccrt_type_ptr r; char s[64]; lccrt_module_ptr m = parent->m; lccrt_check_type_assert( parent, lccrt_type_t); snprintf( s, 64, "$(%ju:%ju:%u:%u:%jd)", parent->ident_num, byteshift, bitsubshift, bitsubsize, bytealign); r = lccrt_type_make( m, LCCRT_TYPE_FIELD, parent, 0, 0, 0, s, 0, bytealign, parent->bytesize, byteshift, bitsubshift, bitsubsize, 0); return (r); } /* lccrt_type_make_field */ /** * Получить тип - структура. */ lccrt_type_ptr lccrt_type_make_struct( lccrt_module_ptr m, uint64_t bytealign, uint64_t bytesize, int num_flds, lccrt_type_ptr *flds, int is_union) { lccrt_type_ptr r; char *s = 0; int k; int j = 0; int len = 0; if ( (num_flds <= 1) ) { /* Не делаем различия между пустыми или состоящими из одного поля структурами и объединениями. */ is_union = 0; } /* Делаем оценку на длину ключа. */ for ( k = 0; k < num_flds; ++k ) { len += lccrt_calc_num_digits( flds[k]->ident_num) + 2; } len += 2 + 128; s = (char *)alloca( len); /* Вычисляем строковое представление ключа. */ j += snprintf( s + j, len - j, is_union ? "<" : "{"); for ( k = 0; k < num_flds; ++k ) { j += snprintf( s + j, len - j, "$%ju", flds[k]->ident_num); } j += snprintf( s + j, len - j, is_union ? ">" : "}"); j += snprintf( s + j, len - j, ":%ju:%ju", bytesize, bytealign); /* Создаем результирующий тип. */ r = lccrt_type_make( m, LCCRT_TYPE_STRUCT, 0, flds, num_flds, 0, s, 0, bytealign, bytesize, 0, 0, 0, is_union); return (r); } /* lccrt_type_make_struct */ /** * Получить тип - функция. */ lccrt_type_ptr lccrt_type_make_func( lccrt_type_ptr rtype, int num_args, lccrt_type_ptr *args) { lccrt_type_ptr r; char *s = 0; int k; int j = 0; int len = 0; lccrt_module_ptr m = rtype->m; /* Делаем оценку на длину ключа. */ for ( k = 0; k < num_args; ++k ) { len += lccrt_calc_num_digits( args[k]->ident_num); } len += 2 + num_args + 1 + lccrt_calc_num_digits( rtype->ident_num); s = (char *)alloca( len); /* Вычисляем строковое представление ключа. */ j += snprintf( s + j, len - j, "$%ju(", rtype->ident_num); for ( k = 0; k < num_args; ++k ) { j += snprintf( s + j, len - j, "$%ju", args[k]->ident_num); } j += snprintf( s + j, len - j, ")"); /* Создаем результирующий тип. */ r = lccrt_type_make( m, LCCRT_TYPE_FUNC, rtype, args, num_args, 0, s, 0, 0, 0, 0, 0, 0, 0); return (r); } /* lccrt_type_make_func */ /** * Создать или реализовать именнованный тип. */ lccrt_type_ptr lccrt_type_make_typename( lccrt_module_ptr m, const char *name, lccrt_type_ptr type) { lccrt_type_ptr r = 0; int len = 0; char *s = 0; int j = 0; //uint64_t bytealign = type ? type->bytealign : 0; //uint64_t bytesize = type ? type->bytesize : 0; len += 2; len += lccrt_calc_num_digits( m->ident_num); len += lccrt_calc_name_shield( name); s = (char *)alloca( len + 1); j += snprintf( s + j, len - j, "@%ju.", m->ident_num); j += lccrt_print_shield_name( s + j, len - j, name); //r = lccrt_type_make( m, LCCRT_TYPE_NAME, type, 0, 0, 0, s, 0, bytealign, bytesize, 0, 0, 0, 0); r = lccrt_type_make( m, LCCRT_TYPE_NAME, type, 0, 0, 0, s, 0, 0, 0, 0, 0, 0, 0); return (r); } /* lccrt_type_make_typename */ /** * Импортирование типа. */ lccrt_type_ptr lccrt_type_import( lccrt_module_ptr m, lccrt_t_ptr type, lccrt_hash_ptr types) { lccrt_type_ptr r = type; lccrt_he_ptr e = 0; if ( (m != lccrt_type_get_module( type)) ) { if ( types ) { e = lccrt_hash_find( types, (uintptr_t)type); r = e ? (lccrt_type_ptr)lccrt_hash_get( e) : 0; } if ( !r ) { int k; lccrt_type_ptr p; int num_args = type->num_args; lccrt_type_ptr *args = 0; if ( lccrt_type_is_int( type) ) { r = lccrt_type_make_int( m, type->bytesize, type->is_sign); } else if ( lccrt_type_is_float( type) ) { r = lccrt_type_make_float( m, type->bytesize); } else if ( lccrt_type_is_bool( type) ) { r = lccrt_type_make_bool( m); } else if ( lccrt_type_is_ellipsis( type) ) { r = lccrt_type_make_ellipsis( m); } else if ( lccrt_type_is_void( type) ) { r = lccrt_type_make_void( m); } else if ( lccrt_type_is_pointer( type) ) { p = lccrt_type_get_parent( type); r = lccrt_type_make_ptr_type( lccrt_type_import( m, p, types)); } else if ( lccrt_type_is_array( type) ) { p = lccrt_type_import( m, lccrt_type_get_parent( type), types); r = lccrt_type_make_array( p, type->num_args); } else if ( lccrt_type_is_field( type) ) { p = lccrt_type_import( m, lccrt_type_get_parent( type), types); r = lccrt_type_make_field( p, type->bytealign, type->byteshift, type->bitsubshift, type->bitsubsize); } else if ( lccrt_type_is_struct( type) ) { args = lccrt_ctx_mallocn( m->ctx, lccrt_type_ptr, num_args); for ( k = 0; k < num_args; ++k ) { args[k] = lccrt_type_import( m, type->args[k], types); } r = lccrt_type_make_struct( m, type->bytealign, type->bytesize, num_args, args, type->is_union); lccrt_ctx_free( m->ctx, args); } else if ( lccrt_type_is_function( type) ) { args = lccrt_ctx_mallocn( m->ctx, lccrt_type_ptr, num_args); for ( k = 0; k < num_args; ++k ) { args[k] = lccrt_type_import( m, type->args[k], types); } p = lccrt_type_import( m, lccrt_type_get_parent( type), types); r = lccrt_type_make_func( p, num_args, args); lccrt_ctx_free( m->ctx, args); } else if ( lccrt_type_is_typename( type) ) { const char *s = type->sym_name; lccrt_assert( s[0] == '@'); lccrt_assert( isdigit( (int)s[1])); lccrt_assert( (s[2] == '.') || (s[1] != '0')); s = s + 2; while ( isdigit( (int)s[0]) ) { ++s; } lccrt_assert( s[0] == '.'); r = lccrt_type_make_typename( m, s + 1, 0); if ( types ) { e = lccrt_hash_push( types, (uintptr_t)type, 0); lccrt_hash_set( e, (uintptr_t)r); p = type->parent; if ( p ) { //lccrt_type_set_parent( r, lccrt_type_import( m, p, types)); } } } else { lccrt_assert( 0); } if ( types && !lccrt_type_is_typename( type) ) { e = lccrt_hash_push( types, (uintptr_t)type, 0); lccrt_hash_set( e, (uintptr_t)r); } } } return (r); } /* lccrt_type_import */ /** * Получить значение поля. */ lccrt_module_ptr lccrt_type_get_module( lccrt_type_ptr type) { lccrt_module_ptr r = type->m; lccrt_check_type_assert( type, lccrt_type_t); return (r); } /* lccrt_type_get_module */ /** * Установить значение поля. В обычной ситуации менять значение поля нельзя, т.к. * значение данного поля влияет на уникальный (хеш-)идентификатор типа. */ void lccrt_type_set_parent( lccrt_type_ptr type, lccrt_type_ptr parent) { lccrt_check_type_assert( type, lccrt_type_t); type->parent = parent; return; } /* lccrt_type_set_parent */ /** * Установить значение поля. В обычной ситуации менять значение поля нельзя, т.к. * значение данного поля влияет на уникальный (хеш-)идентификатор типа. */ void lccrt_type_set_arg( lccrt_type_ptr type, int arg_num, lccrt_type_ptr arg) { lccrt_check_type_assert( type, lccrt_type_t); lccrt_assert( type->args); lccrt_assert( arg_num < type->num_args); type->args[arg_num] = arg; return; } /* lccrt_type_set_arg */ /** * Получить значение поля. */ lccrt_type_ptr lccrt_type_get_arg( lccrt_type_ptr type, int arg_num) { lccrt_type_ptr r; lccrt_check_type_assert( type, lccrt_type_t); lccrt_assert( (arg_num >= 0) && (arg_num < type->num_args)); lccrt_assert( (type->type_name == LCCRT_TYPE_FUNC) || (type->type_name == LCCRT_TYPE_STRUCT)); r = type->args[arg_num]; return (r); } /* lccrt_type_get_arg */ /** * Установить значение поля. */ void lccrt_type_set_typename_bytesize( lccrt_type_ptr type, uint64_t bytesize) { lccrt_assert( lccrt_type_is_typename( type)); type->bytesize = bytesize; return; } /* lccrt_type_set_typename_bytesize */ /** * Установить значение поля. */ void lccrt_type_set_typename_bytealign( lccrt_type_ptr type, uint64_t bytealign) { lccrt_assert( lccrt_type_is_typename( type)); type->bytealign = bytealign; return; } /* lccrt_type_set_typename_bytealign */ /** * Получить значение поля. */ uint64_t lccrt_type_get_bitsubshift( lccrt_type_ptr type) { uint64_t r; lccrt_check_type_assert( type, lccrt_type_t); lccrt_assert( (type->type_name == LCCRT_TYPE_FIELD) || (type->bitsubshift == 0)); r = type->bitsubshift; return (r); } /* lccrt_type_get_bitsubshift */ /** * Получить значение поля. */ uint64_t lccrt_type_get_bitsubsize( lccrt_type_ptr type) { uint64_t r; lccrt_check_type_assert( type, lccrt_type_t); lccrt_assert( (type->type_name == LCCRT_TYPE_FIELD) || (type->bitsubshift == 0)); r = type->bitsubsize; return (r); } /* lccrt_type_get_bitsubsize */ /** * Получить значение поля. */ uint64_t lccrt_type_get_byteshift( lccrt_type_ptr type) { uint64_t r; lccrt_check_type_assert( type, lccrt_type_t); lccrt_assert( (type->type_name == LCCRT_TYPE_FIELD) || (type->byteshift == 0)); r = type->byteshift; return (r); } /* lccrt_type_get_byteshift */ /** * Получить значение поля. */ uint64_t lccrt_type_get_bytealign( lccrt_type_ptr type) { uint64_t r; lccrt_check_type_assert( type, lccrt_type_t); if ( lccrt_type_is_typename( type) && lccrt_type_get_parent( type) ) { r = lccrt_type_get_bytealign( lccrt_type_get_parent( type)); } else { r = type->bytealign; } return (r); } /* lccrt_type_get_bytealign */ /** * Получить значение поля. */ uint64_t lccrt_type_get_bytesize( lccrt_type_ptr type) { uint64_t r; lccrt_check_type_assert( type, lccrt_type_t); if ( lccrt_type_is_typename( type) && lccrt_type_get_parent( type) ) { r = lccrt_type_get_bytesize( lccrt_type_get_parent( type)); } else { r = type->bytesize; } return (r); } /* lccrt_type_get_bytesize */ /** * Получить значение поля. */ lccrt_type_name_t lccrt_type_get_name( lccrt_type_ptr type) { lccrt_type_name_t r; lccrt_check_type_assert( type, lccrt_type_t); r = type->type_name; return (r); } /* lccrt_type_get_name */ /** * Получить значение поля. */ uint64_t lccrt_type_get_num_args( lccrt_type_ptr type) { uint64_t r; lccrt_check_type_assert( type, lccrt_type_t); r = type->num_args; if ( (type->type_name == LCCRT_TYPE_FUNC) || (type->type_name == LCCRT_TYPE_ARRAY) || (type->type_name == LCCRT_TYPE_VECTOR) || (type->type_name == LCCRT_TYPE_STRUCT) ) { lccrt_assert( r >= 0); } else { lccrt_assert( r == 0); } return (r); } /* lccrt_type_get_num_args */ /** * Получить значение поля. */ lccrt_type_ptr lccrt_type_get_parent( lccrt_type_ptr type) { lccrt_type_ptr r; lccrt_check_type_assert( type, lccrt_type_t); r = type->parent; if ( (type->type_name == LCCRT_TYPE_NAME) ) { } else if ( (type->type_name == LCCRT_TYPE_PTR) || (type->type_name == LCCRT_TYPE_NAME) || (type->type_name == LCCRT_TYPE_FUNC) || (type->type_name == LCCRT_TYPE_ARRAY) || (type->type_name == LCCRT_TYPE_VLA_ARRAY) || (type->type_name == LCCRT_TYPE_VECTOR) || (type->type_name == LCCRT_TYPE_FIELD) ) { lccrt_assert( r); } else { lccrt_assert( !r); } return (r); } /* lccrt_type_get_parent */ /** * Получить значение поля. */ lccrt_var_ptr lccrt_type_get_vla_size( lccrt_type_ptr type) { lccrt_var_ptr r; lccrt_check_type_assert( type, lccrt_type_t); lccrt_assert( type->type_name == LCCRT_TYPE_VLA_ARRAY); r = type->vnum; lccrt_assert( 0); return (r); } /* lccrt_type_get_vla_size */ /** * Получить значение поля. */ int lccrt_type_get_sign( lccrt_type_ptr type) { int r; lccrt_check_type_assert( type, lccrt_type_t); r = type->is_sign; if ( (type->type_name != LCCRT_TYPE_INT) ) { lccrt_assert( !r); } return (r); } /* lccrt_type_get_sign */ /** * Подобрать целый тип по битовому размеру. */ lccrt_type_name_int_t lccrt_type_int_find_by_bitsize( uint64_t bitsize) { lccrt_type_name_int_t r; switch ( bitsize ) { case 8: r = LCCRT_INT_SUBTYPE_8; break; case 16: r = LCCRT_INT_SUBTYPE_16; break; case 32: r = LCCRT_INT_SUBTYPE_32; break; case 64: r = LCCRT_INT_SUBTYPE_64; break; case 128: r = LCCRT_INT_SUBTYPE_128; break; default: r = LCCRT_INT_SUBTYPE_LAST; break; } return (r); } /* lccrt_type_int_find_by_bitsize */ /** * Подобрать плавающий тип по битовому размеру. */ lccrt_type_name_float_t lccrt_type_float_find_by_bitsize( uint64_t bitsize) { lccrt_type_name_float_t r; switch ( bitsize ) { case 32: r = LCCRT_FLOAT_SUBTYPE_32; break; case 64: r = LCCRT_FLOAT_SUBTYPE_64; break; case 80: r = LCCRT_FLOAT_SUBTYPE_80; break; case 128: r = LCCRT_FLOAT_SUBTYPE_128; break; default: r = LCCRT_INT_SUBTYPE_LAST; break; } return (r); } /* lccrt_type_float_find_by_bitsize */ /** * Проверить тип на подтип. */ int lccrt_type_is_array( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_ARRAY) ) { r = 1; } return (r); } /* lccrt_type_is_array */ /** * Проверить тип на подтип. */ int lccrt_type_is_vector( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_VECTOR) ) { r = 1; } return (r); } /* lccrt_type_is_vector */ /** * Проверить тип на подтип. */ int lccrt_type_is_struct( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_STRUCT) ) { r = 1; } return (r); } /* lccrt_type_is_struct */ /** * Проверить тип на подтип. */ int lccrt_type_is_bool( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_BOOL) ) { r = 1; } return (r); } /* lccrt_type_is_bool */ /** * Проверить тип на подтип. */ int lccrt_type_is_void( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_VOID) ) { r = 1; } return (r); } /* lccrt_type_is_void */ /** * Проверить тип на подтип. */ int lccrt_type_is_ellipsis( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_ELLIPSIS) ) { r = 1; } return (r); } /* lccrt_type_is_ellipsis */ /** * Проверить тип на подтип. */ int lccrt_type_is_field( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_FIELD) ) { r = 1; } return (r); } /* lccrt_type_is_field */ /** * Проверить тип на подтип. */ int lccrt_type_is_float( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_FLOAT) ) { r = 1; } return (r); } /* lccrt_type_is_float */ /** * Проверить тип на подтип. */ int lccrt_type_is_int( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_INT) ) { r = 1; } return (r); } /* lccrt_type_is_int */ /** * Проверить тип на подтип. */ int lccrt_type_is_typename( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_NAME) ) { r = 1; } return (r); } /* lccrt_type_is_typename */ /** * Проверить тип на подтип. */ int lccrt_type_is_pointer( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_PTR) ) { r = 1; } return (r); } /* lccrt_type_is_pointer */ /** * Проверить тип на подтип. */ int lccrt_type_is_function( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_FUNC) ) { r = 1; } return (r); } /* lccrt_type_is_function */ /** * Проверить тип на подтип. */ int lccrt_type_is_union( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_STRUCT) && (type->is_union) ) { r = 1; } return (r); } /* lccrt_type_is_union */ /** * Проверить тип на подтип. */ int lccrt_type_is_class_elems( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_ARRAY) || (type->type_name == LCCRT_TYPE_VECTOR) || (type->type_name == LCCRT_TYPE_STRUCT) ) { r = 1; } return (r); } /* lccrt_type_is_class_elems */ /** * Проверить тип на подтип. */ int lccrt_type_is_class_struct( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); if ( (type->type_name == LCCRT_TYPE_STRUCT) ) { r = 1; } return (r); } /* lccrt_type_is_class_struct */ /** * Проверяем, что у типа-функции типом последнего аргумента является тип-многоточие. */ int lccrt_type_is_function_var_arg( lccrt_type_ptr type) { int r = 0; lccrt_check_type_assert( type, lccrt_type_t); lccrt_assert( type->type_name == LCCRT_TYPE_FUNC); lccrt_assert( type->num_args >= 0); if ( type->num_args ) { lccrt_type_ptr ta = type->args[type->num_args - 1]; r = (ta->type_name == LCCRT_TYPE_ELLIPSIS); } return (r); } /* lccrt_type_is_function_var_arg */ /** * Вывод на стандартный вывод текстового представления типа. */ int lccrt_type_print( lccrt_type_ptr type, int is_ln) { lccrt_check_type_assert( type, lccrt_type_t); printf( "%s%s", type->sym_name, is_ln ? "\n" : ""); return (0); } /* lccrt_type_ptr */ #if 0 lccrt_type_is_struct lccrt_type_is_union #endif