lccrt/lib/irv/lccrt_type.c

1406 lines
35 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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