lccrt/lib/irv/lccrt_type.c

1406 lines
35 KiB
C
Raw Normal View History

/**
* 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