1406 lines
35 KiB
C
1406 lines
35 KiB
C
/**
|
||
* 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 <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <ctype.h>
|
||
#include <stdarg.h>
|
||
#include <sys/types.h>
|
||
#include <sys/wait.h>
|
||
#include <dlfcn.h>
|
||
|
||
#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
|