lccrt/lib/irv/lccrt_var.c

1608 lines
40 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_var.c - реализация пользовательский интерфейс (динамической) компиляции.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "lccrt_real.h"
/**
* Пропустить typename определения в типе.
*/
lccrt_type_ptr
lccrt_var_skip_typename( lccrt_type_ptr type)
{
while ( (lccrt_type_is_typename( type)
&& lccrt_type_get_parent( type)) )
{
type = lccrt_type_get_parent( type);
}
return (type);
} /* lccrt_var_skip_typename */
/**
* Создание нового инициализатора переменной.
*/
static lccrt_varinit_ptr
lccrt_varinit_new( lccrt_type_ptr type)
{
lccrt_module_ptr m = lccrt_type_get_module( type);
lccrt_context_ptr ctx = lccrt_module_get_context( m);
lccrt_varinit_ptr v = lccrt_ctx_malloc( ctx, lccrt_varinit_t);
lccrt_check_type_assert( type, lccrt_type_t);
type = lccrt_var_skip_typename( type);
memset( v, 0, sizeof( v[0]));
lccrt_check_type_init( v, lccrt_varinit_t);
v->type = type;
v->init_type = LCCRT_VARINIT_LAST;
lccrt_ilist_unit_init( &(v->varinits_unit));
lccrt_ilist_head_insert( &(m->varinits_head), varinits_unit, v);
return (v);
} /* lccrt_varinit_new */
/**
* Удаление инициализатора переменной.
*/
void
lccrt_varinit_delete( lccrt_varinit_ptr v)
{
lccrt_check_type_assert( v, lccrt_varinit_t);
if ( v )
{
lccrt_module_ptr m = lccrt_type_get_module( v->type);
lccrt_context_ptr ctx = lccrt_module_get_context( m);
lccrt_ilist_head_remove( &(m->varinits_head), varinits_unit, v);
lccrt_check_type_done( v, lccrt_varinit_t);
if ( 0 )
{
if ( (v->init_type == LCCRT_VARINIT_STR) )
{
lccrt_ctx_free( ctx, v->data.sval);
} else if ( (v->init_type == LCCRT_VARINIT_ARR) )
{
int64_t i;
for ( i = 0; i < v->num_elems; ++i )
{
lccrt_varinit_delete( v->data.vals[i]);
}
lccrt_ctx_free( ctx, v->data.vals);
}
}
lccrt_ctx_free( ctx, v);
}
return;
} /* lccrt_varinit_delete */
/**
* Создание нового инициализатора переменной.
*/
lccrt_varinit_ptr
lccrt_varinit_new_zero( lccrt_type_ptr type)
{
//lccrt_context_ptr ctx = type->ctx;
lccrt_varinit_ptr v = lccrt_varinit_new( type);
v->init_type = LCCRT_VARINIT_ZERO;
return (v);
} /* lccrt_varinit_new_zero */
/**
* Создание нового инициализатора переменной.
*/
lccrt_varinit_ptr
lccrt_varinit_new_scalar( lccrt_t_ptr type, uint64_t value)
{
//lccrt_context_ptr ctx = type->ctx;
lccrt_varinit_ptr v = lccrt_varinit_new( type);
v->init_type = LCCRT_VARINIT_HEX;
v->data.ival = value;
return (v);
} /* lccrt_varinit_new_scalar */
/**
* Создание нового инициализатора переменной.
*/
lccrt_varinit_ptr
lccrt_varinit_new_str( lccrt_t_ptr type, uint64_t value_len, const char *value)
{
lccrt_context_ptr ctx = type->m->ctx;
lccrt_varinit_ptr v = lccrt_varinit_new( type);
v->init_type = LCCRT_VARINIT_STR;
v->num_elems = value_len;
v->data.sval = lccrt_ctx_mallocn( ctx, char, value_len);
memcpy( v->data.sval, value, value_len);
return (v);
} /* lccrt_varinit_new_str */
/**
* Создание нового инициализатора переменной.
*/
lccrt_varinit_ptr
lccrt_varinit_new_array( lccrt_t_ptr type, uint64_t num_init_elems, lccrt_varinit_ptr *init_data)
{
lccrt_context_ptr ctx = type->m->ctx;
lccrt_varinit_ptr v = lccrt_varinit_new( type);
type = lccrt_var_skip_typename( type);
if ( !((type->type_name == LCCRT_TYPE_ARRAY)
//|| (type->type_name == LCCRT_TYPE_PTR)
|| (type->type_name == LCCRT_TYPE_VECTOR)
|| (type->type_name == LCCRT_TYPE_STRUCT)
|| ((type->type_name == LCCRT_TYPE_INT)
&& (lccrt_type_get_int_subtype_name( 8*type->bytesize) == LCCRT_INT_SUBTYPE_128))
|| ((type->type_name == LCCRT_TYPE_FLOAT)
&& (lccrt_type_get_float_subtype_name( 8*type->bytesize) == LCCRT_FLOAT_SUBTYPE_80))) )
{
lccrt_assert( 0);
}
v->init_type = LCCRT_VARINIT_ARR;
v->num_elems = num_init_elems;
v->data.vals = lccrt_ctx_memdup( ctx, init_data, num_init_elems * sizeof( v->data.vals[0]));
return (v);
} /* lccrt_varinit_new_array */
/**
* Создание нового инициализатора переменной.
*/
lccrt_varinit_ptr
lccrt_varinit_new_addr_var( lccrt_var_ptr var, uint64_t shift)
{
lccrt_type_ptr type = lccrt_type_make_ptr_type( var->type);
lccrt_varinit_ptr v = lccrt_varinit_new( type);
v->init_type = LCCRT_VARINIT_ADDR_VAR;
v->data.var = var;
v->num_elems = shift;
return (v);
} /* lccrt_varinit_new_addr_var */
/**
* Создание нового инициализатора переменной.
*/
lccrt_varinit_ptr
lccrt_varinit_new_addr_func( lccrt_function_ptr func, uint64_t shift)
{
lccrt_type_ptr type = lccrt_type_make_ptr_type( func->sig_type);
lccrt_varinit_ptr v = lccrt_varinit_new( type);
lccrt_check_type_assert( func, lccrt_function_t);
v->init_type = LCCRT_VARINIT_ADDR_FUNC;
v->data.func = func;
v->num_elems = shift;
return (v);
} /* lccrt_varinit_new_addr_func */
/**
* Получить значение поля.
*/
lccrt_type_ptr
lccrt_varinit_get_type( lccrt_varinit_ptr vi)
{
lccrt_type_ptr r;
lccrt_check_type_assert( vi, lccrt_varinit_t);
r = vi->type;
return (r);
} /* lccrt_varinit_get_type */
/**
* Получить значение поля.
*/
lccrt_varinit_inittype_t
lccrt_varinit_get_inittype( lccrt_varinit_ptr vi)
{
lccrt_varinit_inittype_t r;
lccrt_check_type_assert( vi, lccrt_varinit_t);
r = vi->init_type;
return (r);
} /* lccrt_varinit_get_inittype */
/**
* Получить значение поля.
*/
uint64_t
lccrt_varinit_get_num_elems( lccrt_varinit_ptr vi)
{
uint64_t r = 0;
if ( lccrt_varinit_is_array( vi)
|| lccrt_varinit_is_str( vi)
|| lccrt_varinit_is_addr_var( vi)
|| lccrt_varinit_is_addr_func( vi) )
{
r = vi->num_elems;
}
return (r);
} /* lccrt_varinit_get_num_elems */
/**
* Получить значение поля.
*/
uint64_t
lccrt_varinit_get_hex64( lccrt_varinit_ptr vi)
{
uint64_t r = 0;
lccrt_assert( lccrt_varinit_is_hex( vi));
r = vi->data.ival;
return (r);
} /* lccrt_varinit_get_hex64 */
/**
* Получить значение поля.
*/
uint64_t
lccrt_varinit_get_zero_or_hex64( lccrt_varinit_ptr vi)
{
uint64_t r = 0;
if ( lccrt_varinit_is_zero( vi) )
{
lccrt_assert( vi->data.ival == 0);
} else if ( lccrt_varinit_is_hex( vi) )
{
r = vi->data.ival;
} else
{
lccrt_assert( 0);
}
return (r);
} /* lccrt_varinit_get_zero_or_hex64 */
/**
* Получить значение поля.
*/
const char *
lccrt_varinit_get_str( lccrt_varinit_ptr vi)
{
const char *r;
lccrt_assert( lccrt_varinit_is_str( vi));
r = vi->data.sval;
return (r);
} /* lccrt_varinit_get_str */
/**
* Получить значение поля.
*/
lccrt_varinit_ptr
lccrt_varinit_get_elem( lccrt_varinit_ptr vi, uint64_t elem_num)
{
lccrt_varinit_ptr r;
lccrt_assert( lccrt_varinit_is_array( vi) || lccrt_varinit_is_str( vi));
lccrt_assert( (0 <= elem_num) && (elem_num < vi->num_elems));
r = vi->data.vals[ elem_num];
return (r);
} /* lccrt_varinit_get_elem */
/**
* Получить значение поля.
*/
lccrt_function_ptr
lccrt_varinit_get_addr_func( lccrt_varinit_ptr vi)
{
lccrt_function_ptr r;
lccrt_assert( lccrt_varinit_is_addr_func( vi));
r = vi->data.func;
return (r);
} /* lccrt_varinit_get_addr_func */
/**
* Получить значение поля.
*/
lccrt_var_ptr
lccrt_varinit_get_addr_var( lccrt_varinit_ptr vi)
{
lccrt_var_ptr r;
lccrt_assert( lccrt_varinit_is_addr_var( vi));
r = vi->data.var;
return (r);
} /* lccrt_varinit_get_addr_var */
/**
* Проверить подтип.
*/
int
lccrt_varinit_is_zero( lccrt_varinit_ptr vi)
{
int r = 0;
lccrt_check_type_assert( vi, lccrt_varinit_t);
if ( (vi->init_type == LCCRT_VARINIT_ZERO) )
{
r = 1;
}
return (r);
} /* lccrt_varinit_is_zero */
/**
* Проверить подтип.
*/
int
lccrt_varinit_is_hex( lccrt_varinit_ptr vi)
{
int r = 0;
lccrt_check_type_assert( vi, lccrt_varinit_t);
if ( (vi->init_type == LCCRT_VARINIT_HEX) )
{
r = 1;
}
return (r);
} /* lccrt_varinit_is_hex */
/**
* Проверить подтип.
*/
int
lccrt_varinit_is_zero_or_hex( lccrt_varinit_ptr vi)
{
int r = 0;
r = lccrt_varinit_is_zero( vi) || lccrt_varinit_is_hex( vi);
return (r);
} /* lccrt_varinit_is_zero_or_hex */
/**
* Проверить подтип.
*/
int
lccrt_varinit_is_str( lccrt_varinit_ptr vi)
{
int r = 0;
lccrt_check_type_assert( vi, lccrt_varinit_t);
if ( (vi->init_type == LCCRT_VARINIT_STR) )
{
r = 1;
}
return (r);
} /* lccrt_varinit_is_str */
/**
* Проверить подтип.
*/
int
lccrt_varinit_is_array( lccrt_varinit_ptr vi)
{
int r = 0;
lccrt_check_type_assert( vi, lccrt_varinit_t);
if ( (vi->init_type == LCCRT_VARINIT_ARR) )
{
r = 1;
}
return (r);
} /* lccrt_varinit_is_array */
/**
* Проверить подтип.
*/
int
lccrt_varinit_is_addr_var( lccrt_varinit_ptr vi)
{
int r = 0;
lccrt_check_type_assert( vi, lccrt_varinit_t);
if ( (vi->init_type == LCCRT_VARINIT_ADDR_VAR) )
{
r = 1;
}
return (r);
} /* lccrt_varinit_is_addr_var */
/**
* Проверить подтип.
*/
int
lccrt_varinit_is_addr_func( lccrt_varinit_ptr vi)
{
int r = 0;
lccrt_check_type_assert( vi, lccrt_varinit_t);
if ( (vi->init_type == LCCRT_VARINIT_ADDR_FUNC) )
{
r = 1;
}
return (r);
} /* lccrt_varinit_is_addr_func */
/**
* Создание новой переменной.
*/
lccrt_var_ptr
lccrt_var_new( void *holder, lccrt_var_loc_t loc, lccrt_t_ptr type, const char *name,
const char *asm_name, lccrt_link_t vlink, unsigned align)
{
lccrt_var_ptr v = 0;
lccrt_context_ptr ctx = 0;
lccrt_module_ptr m = 0;
lccrt_function_ptr f = 0;
lccrt_he_ptr e = 0;
lccrt_asmlink_t link = lccrt_link_unpack( vlink);
lccrt_assert( lccrt_type_get_bytesize( type) >= 0);
type = lccrt_var_skip_typename( type);
if ( (name
&& name[0] == '\01') )
{
name++;
}
if ( (asm_name
&& asm_name[0] == '\01') )
{
asm_name++;
}
if ( asm_name
&& (asm_name[0] == 0) )
{
asm_name = name;
}
if ( (lccrt_type_get_bytesize( type) == 0) )
{
//lccrt_assert( lccrt_loc_is_ext( loc) || (link.bnd == LCCRT_LINK_BND_WEAK));
lccrt_assert( lccrt_type_is_array( type) || lccrt_type_is_struct( type) || lccrt_type_is_function( type));
}
if ( lccrt_loc_is_global( loc) )
{
/* Глобальная переменная модуля. */
m = (lccrt_module_ptr)holder;
name = lccrt_module_name_new_global( m, name);
if ( (loc == LCCRT_VAR_LOC_GLOB) )
{
lccrt_assert( link.bnd != LCCRT_LINK_BND_NO);
} else if ( (loc == LCCRT_VAR_LOC_CONSTARG) )
{
lccrt_assert( link.bnd == LCCRT_LINK_BND_LOCAL);
lccrt_assert( link.vis == LCCRT_LINK_VIS_DEFAULT);
lccrt_assert( link.tls == LCCRT_LINK_TLS_NO);
lccrt_assert( link.is_cnst && !link.is_alias);
} else
{
if ( link.is_alias )
{
if ( !((link.bnd == LCCRT_LINK_BND_GLOBAL)
|| (link.bnd == LCCRT_LINK_BND_WEAK)
|| (link.bnd == LCCRT_LINK_BND_LOCAL)) )
{
lccrt_assert( 0);
}
} else
{
if ( !((link.bnd == LCCRT_LINK_BND_GLOBAL)
|| (link.bnd == LCCRT_LINK_BND_WEAK)) )
{
lccrt_assert( 0);
}
}
}
} else if ( lccrt_loc_is_local( loc) )
{
/* Локальная переменная функции. */
lccrt_assert( link.bnd == LCCRT_LINK_BND_NO);
lccrt_assert( link.vis == LCCRT_LINK_VIS_DEFAULT);
lccrt_assert( link.tls == LCCRT_LINK_TLS_NO);
f = (lccrt_function_ptr)holder;
m = (lccrt_module_ptr)f->module;
name = lccrt_function_name_new_local( f, name);
} else
{
lccrt_assert( 0);
}
ctx = m->ctx;
lccrt_check_type_assert( f, lccrt_function_t);
lccrt_check_type_assert( m, lccrt_module_t);
lccrt_check_type_assert( ctx, lccrt_context_t);
lccrt_check_type_assert( type, lccrt_type_t);
/* Проводим поиск на наличие переменной с заданным именем. */
e = lccrt_hash_find( f ? f->lvars : m->gvars, (uintptr_t)name);
if ( e )
{
/* Переменная уже создана. */
v = (lccrt_var_ptr)lccrt_hash_get( e);
lccrt_assert( lccrt_str_eqz( asm_name, v->asm_name));
lccrt_ctx_free( ctx, name);
if ( !((loc == LCCRT_VAR_LOC_GLOB)
&& (v->loc == LCCRT_VAR_LOC_EXT)) )
{
lccrt_assert( type == v->type);
}
/* Проверяем (и изменяем для декларации) тип размещения переменной. */
switch ( loc )
{
case LCCRT_VAR_LOC_GLOB:
/* Создается определение, поэтому меняем тип размещения, который
должен быть декларацией. */
lccrt_assert( v->loc == LCCRT_VAR_LOC_EXT);
v->type = type;
v->loc = loc;
v->align = v->align ? v->align : align;
break;
case LCCRT_VAR_LOC_EXT:
lccrt_assert( lccrt_var_is_global( v));
align = align ? align : v->align;
break;
case LCCRT_VAR_LOC_LOCAL:
case LCCRT_VAR_LOC_ARG:
case LCCRT_VAR_LOC_SYSARG:
lccrt_assert( loc == v->loc);
break;
default:
break;
}
/* Проверяем согласованность выравниваний. */
lccrt_assert( align == v->align);
lccrt_assert( link.vis == v->link.vis);
lccrt_assert( link.tls == v->link.tls);
lccrt_assert( link.is_cnst == v->link.is_cnst);
lccrt_assert( link.is_alias == v->link.is_alias);
} else
{
/* Создаем новую переменную. */
v = lccrt_ctx_malloc( ctx, lccrt_var_t);
memset( v, 0, sizeof( v[0]));
lccrt_check_type_init( v, lccrt_var_t);
v->holder = holder;
v->loc = loc;
v->type = type;
v->name = name;
v->asm_name = lccrt_ctx_copy_str( ctx, asm_name);
lccrt_ilist_unit_init( &(v->vars_unit));
v->align = align;
v->link = link;
v->arg_num = -1;
if ( f )
{
f->lvars_num++;
v->ident_num = f->lvars_num;
lccrt_ilist_head_insert( &(f->lvars_head), vars_unit, v);
} else
{
m->gvars_num++;
v->ident_num = m->gvars_num;
lccrt_ilist_head_insert( &(m->gvars_head), vars_unit, v);
}
if ( (link.bnd == LCCRT_LINK_BND_LOCAL) )
{
}
e = lccrt_hash_push( f ? f->lvars : m->gvars, (uintptr_t)name, 0);
lccrt_hash_set( e, (uintptr_t)v);
}
return (v);
} /* lccrt_var_new */
/**
* Удаление переменной.
*/
void
lccrt_var_delete( lccrt_var_ptr v)
{
lccrt_module_ptr m = lccrt_var_get_module( v);
lccrt_context_ptr ctx = m->ctx;
lccrt_check_type_assert( v, lccrt_var_t);
/* Корректируем структуру списка переменных. */
if ( lccrt_var_is_local( v) )
{
lccrt_function_ptr f = v->holder;
lccrt_check_type_assert( f, lccrt_function_t);
lccrt_ilist_head_remove( &(f->lvars_head), vars_unit, v);
} else
{
lccrt_module_ptr m = v->holder;
lccrt_check_type_assert( m, lccrt_module_t);
lccrt_ilist_head_remove( &(m->gvars_head), vars_unit, v);
}
v->einfo = lccrt_einfo_link_delete_chain( v->einfo);
//lccrt_varinit_delete( v->init_value);
lccrt_ctx_free( ctx, v->name);
lccrt_ctx_free( ctx, v->asm_name);
lccrt_ctx_free( ctx, v->section_name);
lccrt_ctx_free( ctx, v->comdat);
lccrt_check_type_done( v, lccrt_var_t);
lccrt_ctx_free( ctx, v);
return;
} /* lccrt_var_delete */
/**
* Создание константы.
*/
lccrt_var_ptr
lccrt_var_new_constarg( lccrt_m_ptr m, lccrt_t_ptr type, lccrt_varinit_ptr vi)
{
char name[256];
lccrt_link_t lnk;
lccrt_var_ptr r = 0;
int cind = -1;
int tind = -1;
lccrt_type_ptr u32 = lccrt_type_make_u32( m);
lccrt_type_ptr u64 = lccrt_type_make_u64( m);
if ( (type == u32)
&& lccrt_varinit_is_zero_or_hex( vi) )
{
int32_t v32 = lccrt_varinit_get_zero_or_hex64( vi);
if ( (LCCRT_MODULE_CARG_MIN <= v32)
&& (v32 <= LCCRT_MODULE_CARG_MAX) )
{
tind = 0;
cind = (v32 - LCCRT_MODULE_CARG_MIN);
}
} else if ( (type == u64)
&& lccrt_varinit_is_zero_or_hex( vi) )
{
int64_t v64 = lccrt_varinit_get_zero_or_hex64( vi);
if ( (LCCRT_MODULE_CARG_MIN <= v64)
&& (v64 <= LCCRT_MODULE_CARG_MAX) )
{
tind = 1;
cind = (v64 - LCCRT_MODULE_CARG_MIN);
}
}
if ( (cind >= 0)
&& m->carg_vars[tind][cind] )
{
r = m->carg_vars[tind][cind];
} else
{
snprintf( name, 256, "__lccrt_c%ju", m->cargs_name_id);
m->cargs_name_id++;
lnk = lccrt_link_get( LCCRT_LINK_BND_LOCAL, LCCRT_LINK_VIS_DEFAULT,
LCCRT_LINK_TLS_NO, 1, 0);
r = lccrt_var_new( m, LCCRT_VAR_LOC_CONSTARG, type, name, 0, lnk, 0);
lccrt_var_set_init_value_reduce( r, vi);
if ( (cind >= 0) )
{
m->carg_vars[tind][cind] = r;
}
}
return (r);
} /* lccrt_var_new_constarg */
/**
* Создание целочисленной константы.
*/
lccrt_var_ptr
lccrt_var_new_constarg_hex( lccrt_m_ptr m, lccrt_t_ptr type, uint64_t value)
{
lccrt_var_ptr r;
r = lccrt_var_new_constarg( m, type, lccrt_varinit_new_scalar( type, value));
return (r);
} /* lccrt_var_new_constarg_hex */
/**
* Создание целочисленной константы.
*/
lccrt_var_ptr
lccrt_var_new_constarg_str( lccrt_module_ptr m, uint64_t s_len, const char *s)
{
lccrt_varinit_ptr vi;
lccrt_var_ptr r = 0;
lccrt_type_ptr tu8 = lccrt_type_make_u8( m);
vi = lccrt_varinit_new_str( lccrt_type_make_pbyte( m), s_len, s);
r = lccrt_var_new_constarg( m, lccrt_type_make_array( tu8, s_len), vi);
return (r);
} /* lccrt_var_new_constarg_str */
/**
* Создание нового заголовка глобальной переменной.
*/
lccrt_var_ptr
lccrt_var_new_declaration( lccrt_m_ptr m, lccrt_t_ptr type, const char *name, lccrt_link_t link)
{
lccrt_var_ptr v;
v = lccrt_var_new( m, LCCRT_VAR_LOC_EXT, type, name, 0, link, 0);
return (v);
} /* lccrt_var_new_declaration */
/**
* Создание новой локальной переменной.
*/
lccrt_var_ptr
lccrt_var_new_local( lccrt_f_ptr f, lccrt_t_ptr type, const char *name)
{
lccrt_var_ptr v;
lccrt_link_t link = lccrt_link_get( 0, 0, 0, 0, 0);
if ( !name )
{
name = lccrt_function_name_new_local( f, 0);
}
v = lccrt_var_new( f, LCCRT_VAR_LOC_LOCAL, type, name, 0, link, 0);
return (v);
} /* lccrt_var_new_local */
/**
* Создание новой локальной переменной.
*/
lccrt_var_ptr
lccrt_var_new_asm( lccrt_f_ptr f, lccrt_t_ptr type, const char *asm_text, const char *asm_cnstr)
{
lccrt_var_ptr v;
lccrt_link_t link = lccrt_link_get( 0, 0, 0, 0, 0);
v = lccrt_var_new( f, LCCRT_VAR_LOC_ASM, type, asm_text, asm_cnstr, link, 0);
return (v);
} /* lccrt_var_new_asm */
lccrt_type_ptr
lccrt_var_expand_array( lccrt_var_ptr var, lccrt_type_ptr type)
{
lccrt_type_ptr r = 0;
lccrt_check_type_assert( var, lccrt_var_t);
lccrt_check_type_assert( type, lccrt_type_t);
if ( (var->type == type) )
{
r = type;
} else
{
lccrt_assert( lccrt_type_is_array( var->type));
lccrt_assert( lccrt_type_is_array( type));
lccrt_assert( lccrt_type_get_parent( type) == lccrt_type_get_parent( var->type));
if ( (lccrt_type_get_num_args( type) > lccrt_type_get_num_args( var->type)) )
{
r = type;
var->type = type;
} else
{
r = var->type;
}
}
return (r);
} /* lccrt_var_expand_array */
/**
* Получить значение поля.
*/
lccrt_module_ptr
lccrt_var_get_module( lccrt_var_ptr var)
{
lccrt_module_ptr r;
lccrt_check_type_assert( var, lccrt_var_t);
if ( lccrt_var_is_local( var) )
{
r = lccrt_function_get_module( var->holder);
} else
{
r = var->holder;
}
return (r);
} /* lccrt_var_get_module */
/**
* Получить для переменной значение атрибута.
*/
static int
lccrt_var_get_attr( lccrt_v_ptr v, lccrt_var_attr_name_t attr)
{
int r;
int k = attr / 64;
int j = attr % 64;
lccrt_check_type_assert( v, lccrt_var_t);
r = (v->attrs[k] >> j) & 0x1;
return (r);
} /* lccrt_var_get_attr */
/**
* Установить для переменной значение атрибута.
*/
static int
lccrt_var_set_attr( lccrt_v_ptr v, lccrt_var_attr_name_t attr, int value)
{
int k = attr / 64;
int j = attr % 64;
uint64_t bit = 1ULL << j;
uint64_t value_bit = value ? bit : 0ULL;
int r = lccrt_var_get_attr( v, attr);
v->attrs[k] = (v->attrs[k] & (~bit)) | value_bit;
return (r);
} /* lccrt_var_set_attr */
/**
* Скопировать значение булевых атрибутов.
*/
void
lccrt_var_copy_attrs( lccrt_v_ptr dst, lccrt_v_ptr src)
{
int i;
lccrt_check_type_assert( dst, lccrt_var_t);
lccrt_check_type_assert( src, lccrt_var_t);
for ( i = 0; i < LCCRT_FUNC_ATTRS_LENGTH; ++i )
{
dst->attrs[i] = src->attrs[i];
}
return;
} /* lccrt_var_copy_attrs */
/**
* Получить для переменной значение атрибута.
*/
int
lccrt_var_get_attr_common( lccrt_v_ptr v)
{
int r = lccrt_var_get_attr( v, LCCRT_VAR_ATTR_COMMON);
return (r);
} /* lccrt_var_get_attr_common */
/**
* Установить для переменной значение атрибута.
*/
int
lccrt_var_set_attr_common( lccrt_v_ptr v, int value)
{
int r = lccrt_var_set_attr( v, LCCRT_VAR_ATTR_COMMON, value);
return (r);
} /* lccrt_var_set_attr_common */
/**
* Получить для переменной значение атрибута.
*/
int
lccrt_var_get_attr_used( lccrt_v_ptr v)
{
int r = lccrt_var_get_attr( v, LCCRT_VAR_ATTR_USED);
return (r);
} /* lccrt_var_get_attr_used */
/**
* Установить для переменной значение атрибута.
*/
int
lccrt_var_set_attr_used( lccrt_v_ptr v, int value)
{
int r = lccrt_var_set_attr( v, LCCRT_VAR_ATTR_USED, value);
return (r);
} /* lccrt_var_set_attr_used */
/**
* Получить для переменной значение атрибута.
*/
int
lccrt_var_get_attr_restrict( lccrt_v_ptr v)
{
int r = lccrt_var_get_attr( v, LCCRT_VAR_ATTR_RESTRICT);
return (r);
} /* lccrt_var_get_attr_restrict */
/**
* Установить для переменной значение атрибута.
*/
int
lccrt_var_set_attr_restrict( lccrt_v_ptr v, int value)
{
int r = lccrt_var_set_attr( v, LCCRT_VAR_ATTR_RESTRICT, value);
return (r);
} /* lccrt_var_set_attr_restrict */
/**
* Получить значение поля.
*/
const char *
lccrt_var_get_comdat( lccrt_var_ptr var)
{
const char *r;
lccrt_check_type_assert( var, lccrt_var_t);
r = var->comdat;
return (r);
} /* lccrt_var_get_comdat */
/**
* Установить значение поля.
*/
void
lccrt_var_set_comdat( lccrt_var_ptr var, const char *comdat)
{
lccrt_ctx_ptr ctx = lccrt_module_get_context( lccrt_var_get_module( var));
lccrt_check_type_assert( var, lccrt_var_t);
lccrt_assert( !var->comdat);
//lccrt_ctx_free( ctx, var->comdat);
var->comdat = lccrt_ctx_copy_str( ctx, comdat);
return;
} /* lccrt_var_set_comdat */
/**
* Получить значение поля.
*/
uint64_t
lccrt_var_get_bytesize( lccrt_var_ptr var)
{
uint64_t r;
r = lccrt_type_get_bytesize( lccrt_var_get_type( var));
return (r);
} /* lccrt_var_get_bytesize */
/**
* Получить значение поля.
*/
const char *
lccrt_var_get_name( lccrt_var_ptr var)
{
const char *r;
lccrt_check_type_assert( var, lccrt_var_t);
r = var->name;
return (r);
} /* lccrt_var_get_name */
/**
* Получить значение поля.
*/
const char *
lccrt_var_get_asm_name( lccrt_var_ptr var)
{
const char *r;
lccrt_check_type_assert( var, lccrt_var_t);
r = var->asm_name;
return (r);
} /* lccrt_var_get_asm_name */
/**
* Получить значение поля.
*/
lccrt_type_ptr
lccrt_var_get_type( lccrt_var_ptr var)
{
lccrt_type_ptr r;
lccrt_check_type_assert( var, lccrt_var_t);
r = var->type;
return (r);
} /* lccrt_var_get_type */
/**
* Получить значение поле.
*/
unsigned
lccrt_var_get_align( lccrt_var_ptr var)
{
unsigned r;
lccrt_check_type_assert( var, lccrt_var_t);
r = var->align;
return (r);
} /* lccrt_var_get_align */
/**
* Получить значение поля.
*/
lccrt_var_ptr
lccrt_var_get_next_var( lccrt_var_ptr var)
{
lccrt_var_ptr r;
lccrt_check_type_assert( var, lccrt_var_t);
r = var->vars_unit.next;
return (r);
} /* lccrt_var_get_next_var */
/**
* Получить значение поля.
*/
lccrt_varinit_ptr
lccrt_var_get_init_value( lccrt_var_ptr var)
{
lccrt_varinit_ptr r;
lccrt_check_type_assert( var, lccrt_var_t);
r = var->init_value;
return (r);
} /* lccrt_var_get_init_value */
/**
* Получить значение поля.
*/
lccrt_link_t
lccrt_var_get_link( lccrt_var_ptr var)
{
lccrt_link_t r;
lccrt_check_type_assert( var, lccrt_var_t);
r = lccrt_link_get( var->link.bnd, var->link.vis, var->link.tls, var->link.is_cnst, var->link.is_alias);
return (r);
} /* lccrt_var_get_link */
/**
* Получить значение поля.
*/
lccrt_var_loc_t
lccrt_var_get_loc( lccrt_var_ptr var)
{
lccrt_var_loc_t r;
lccrt_check_type_assert( var, lccrt_var_t);
r = var->loc;
return (r);
} /* lccrt_var_get_loc */
/**
* Получить значение поля.
*/
const char *
lccrt_var_get_section( lccrt_var_ptr var)
{
lccrt_check_type_assert( var, lccrt_var_t);
return (var->section_name);
} /* lccrt_var_get_section */
/**
* Установить значение поля.
*/
void
lccrt_var_set_section( lccrt_var_ptr var, const char *section_name)
{
lccrt_ctx_ptr ctx = lccrt_module_get_context( lccrt_var_get_module( var));
lccrt_check_type_assert( var, lccrt_var_t);
if ( var->section_name )
{
lccrt_ctx_free( ctx, var->section_name);
}
var->section_name = lccrt_ctx_copy_str( ctx, section_name);
return;
} /* lccrt_var_set_section */
/**
* Получить значение поля.
*/
int
lccrt_var_is_local( lccrt_var_ptr var)
{
int r = 0;
lccrt_check_type_assert( var, lccrt_var_t);
r = lccrt_loc_is_local( var->loc);
return (r);
} /* lccrt_var_is_local */
/**
* Получить значение поля.
*/
int
lccrt_var_is_global( lccrt_var_ptr var)
{
int r = 0;
lccrt_check_type_assert( var, lccrt_var_t);
r = lccrt_loc_is_global( var->loc);
return (r);
} /* lccrt_var_is_global */
/**
* Получить значение поля.
*/
int
lccrt_var_is_const( lccrt_var_ptr var)
{
int r = 0;
lccrt_check_type_assert( var, lccrt_var_t);
r = var->link.is_cnst;
lccrt_assert( !r || lccrt_var_is_global( var));
return (r);
} /* lccrt_var_is_const */
/**
* Получить значение поля.
*/
int
lccrt_var_get_num_defs( lccrt_var_ptr v)
{
int r = v->num_defs;
lccrt_check_type_assert( v, lccrt_var_t);
return (r);
} /* lccrt_var_get_num_defs */
/**
* Установить значение поля.
*/
int
lccrt_var_set_num_defs( lccrt_var_ptr v, int num_defs)
{
int r = v->num_defs;
lccrt_check_type_assert( v, lccrt_var_t);
v->num_defs = num_defs;
return (r);
} /* lccrt_var_set_num_defs */
/**
* Назначение переменной инициализатора.
*/
void
lccrt_var_set_init_value( lccrt_var_ptr var,
lccrt_varinit_ptr value)
{
lccrt_module_ptr m = lccrt_type_get_module( lccrt_var_get_type( var));
int ptr_bytesize = lccrt_module_is_ptr32( m) ? 4 : 8;
lccrt_check_type_assert( var, lccrt_var_t);
lccrt_check_type_assert( value, lccrt_varinit_t);
if ( (var->type == value->type) )
{
} else if ( (var->type->type_name == LCCRT_TYPE_INT) )
{
if ( (value->type->type_name == LCCRT_TYPE_ARRAY)
&& (var->type->bytesize == 16) )
{
} else if ( (value->type->type_name == LCCRT_TYPE_PTR)
&& (var->type->bytesize == ptr_bytesize) )
{
} else
{
lccrt_assert( 0);
}
} else if ( (var->type->type_name == LCCRT_TYPE_PTR) )
{
if ( (value->type->type_name == LCCRT_TYPE_INT) )
{
lccrt_assert( lccrt_type_get_bytesize( value->type) <= ptr_bytesize);
} else
{
lccrt_assert( 0);
}
} else
{
lccrt_assert( 0);
}
var->init_value = value;
return;
} /* lccrt_var_set_init_value */
/**
* Назначение переменной инициализатора (с приведением типа инициализатора).
*/
void
lccrt_var_set_init_value_reduce( lccrt_var_ptr var,
lccrt_varinit_ptr value)
{
lccrt_module_ptr m = lccrt_type_get_module( lccrt_var_get_type( var));
int ptr_bytesize = lccrt_module_is_ptr32( m) ? 4 : 8;
lccrt_check_type_assert( var, lccrt_var_t);
lccrt_check_type_assert( value, lccrt_varinit_t);
if ( (var->type != value->type) )
{
lccrt_type_ptr tv = lccrt_type_get_parent( var->type);
lccrt_type_ptr ti = lccrt_type_get_parent( value->type);
if ( (var->type->type_name == LCCRT_TYPE_INT) )
{
if ( (value->type->type_name == LCCRT_TYPE_ARRAY)
&& (var->type->bytesize == 16) )
{
} else if ( (value->type->type_name == LCCRT_TYPE_PTR)
&& (var->type->bytesize == ptr_bytesize) )
{
} else
{
lccrt_assert( 0);
}
} else if ( (var->type->type_name == LCCRT_TYPE_PTR) )
{
if ( (value->type->type_name == LCCRT_TYPE_INT) )
{
} else
{
lccrt_assert( value->type->type_name == LCCRT_TYPE_PTR);
if ( (tv->type_name == LCCRT_TYPE_NAME) )
{
//lccrt_assert( tv->parent == (lccrt_type_ptr)ti);
value->type = var->type;
} else if ( (ti->type_name == LCCRT_TYPE_NAME) )
{
//lccrt_assert( ti->parent == (lccrt_type_ptr)tv);
value->type = var->type;
} else if ( (value->type->type_name == LCCRT_TYPE_PTR) )
{
value->type = var->type;
} else
{
lccrt_assert( 0);
}
}
} else if ( (var->type->type_name == LCCRT_TYPE_ARRAY) )
{
lccrt_module_ptr m = var->type->m;
lccrt_type_ptr pi = lccrt_type_get_parent( value->type);
lccrt_type_ptr pv = lccrt_type_get_parent( var->type);
lccrt_type_ptr i8 = lccrt_type_make_int( m, 1, 1);
lccrt_type_ptr u8 = lccrt_type_make_int( m, 1, 0);
lccrt_assert( value->type->type_name == LCCRT_TYPE_PTR);
lccrt_assert( (pi == i8) || (pi == u8));
lccrt_assert( (pv == i8) || (pv == u8));
lccrt_assert( value->init_type == LCCRT_VARINIT_STR);
lccrt_assert( value->num_elems == var->type->num_args);
value->type = var->type;
} else
{
lccrt_assert( 0);
}
}
lccrt_var_set_init_value( var, value);
return;
} /* lccrt_var_set_init_value_reduce */
/**
* Получить значение поля.
*/
int
lccrt_var_is_constarg( lccrt_var_ptr var)
{
int r = 0;
lccrt_check_type_assert( var, lccrt_var_t);
if ( lccrt_loc_is_constarg( var->loc) )
{
r = 1;
lccrt_assert( var->link.bnd == LCCRT_LINK_BND_LOCAL);
lccrt_assert( var->link.vis == LCCRT_LINK_VIS_DEFAULT);
lccrt_assert( var->link.tls == LCCRT_LINK_TLS_NO);
lccrt_assert( var->link.is_cnst && !var->link.is_alias);
lccrt_assert( !lccrt_var_get_attr_used( var));
lccrt_assert( !lccrt_var_get_attr_common( var));
}
return (r);
} /* lccrt_var_is_constarg */
/**
* Получить значение поля.
*/
int
lccrt_var_is_constarg_hex( lccrt_var_ptr var)
{
int r = 0;
if ( lccrt_var_is_constarg( var)
&& var->init_value
&& lccrt_varinit_is_hex( var->init_value) )
{
r = 1;
}
return (r);
} /* lccrt_var_is_constarg_hex */
/**
* Получить значение поля.
*/
int
lccrt_var_is_constarg_int( lccrt_var_ptr var)
{
int r = 0;
if ( lccrt_var_is_constarg( var)
&& var->init_value
&& lccrt_type_is_int( var->type) )
{
r = 1;
}
return (r);
} /* lccrt_var_is_constarg_int */
/**
* Переменная реализует строковую константy.
*/
int
lccrt_var_is_constarg_str( lccrt_var_ptr v)
{
int r = 0;
lccrt_check_type_assert( v, lccrt_var_t);
if ( lccrt_var_is_constarg( v)
&& v->init_value
&& ((v->type == lccrt_type_make_pchar( v->type->m))
|| ((v->type->type_name == LCCRT_TYPE_ARRAY)
&& (v->type->parent == lccrt_type_make_u8( v->type->m))))
&& ((v->init_value->init_type == LCCRT_VARINIT_STR)
|| (v->init_value->init_type == LCCRT_VARINIT_ZERO)) )
{
r = 1;
}
return (r);
} /* lccrt_var_is_constarg_str */
/**
* Переменная реализует константy адрес функции.
*/
int
lccrt_var_is_constarg_addr_func( lccrt_var_ptr v)
{
int r = 0;
lccrt_varinit_ptr vi = v->init_value;
lccrt_check_type_assert( v, lccrt_var_t);
if ( vi
&& v->link.is_cnst
&& ((vi->init_type == LCCRT_VARINIT_ADDR_FUNC)
|| (vi->init_type == LCCRT_VARINIT_ZERO))
&& (v->type->type_name == LCCRT_TYPE_PTR)
&& (v->type->parent->type_name == LCCRT_TYPE_FUNC) )
{
r = 1;
}
return (r);
} /* lccrt_var_is_constarg_addr_func */
/**
* Получить значение целочисленной константы.
*/
uint64_t
lccrt_var_get_constarg_hex64( lccrt_var_ptr v)
{
uint64_t r = 0;
lccrt_varinit_ptr vi = v->init_value;
lccrt_assert( lccrt_var_is_constarg( v));
if ( (vi->init_type == LCCRT_VARINIT_ZERO) )
{
} else if ( (vi->init_type == LCCRT_VARINIT_HEX) )
{
r = vi->data.ival;
} else
{
lccrt_assert( 0);
}
return (r);
} /* lccrt_var_get_constarg_hex64 */
/**
* Получить значение целочисленной константы.
*/
int64_t
lccrt_var_get_constarg_int64( lccrt_var_ptr v)
{
int64_t r = 0;
lccrt_varinit_ptr vi = v->init_value;
lccrt_assert( lccrt_var_is_constarg_int( v));
if ( (vi->init_type == LCCRT_VARINIT_ZERO) )
{
} else if ( (vi->init_type == LCCRT_VARINIT_HEX) )
{
lccrt_type_ptr t = v->type;
if ( (t->bytesize == 1) )
{
r = (char)vi->data.ival;
} else if ( (t->bytesize == 2) )
{
r = (short)vi->data.ival;
} else if ( (t->bytesize == 4) )
{
r = (int)vi->data.ival;
} else if ( (t->bytesize == 8) )
{
r = vi->data.ival;
} else
{
lccrt_assert( 0);
}
} else
{
lccrt_assert( 0);
}
return (r);
} /* lccrt_var_get_constarg_int64 */
/**
* Получить значение строковой константы.
*/
const char *
lccrt_var_get_constarg_str( lccrt_var_ptr v)
{
const char *r = 0;
lccrt_varinit_ptr vi = v->init_value;
if ( !lccrt_var_is_constarg_str( v) )
{
printf( "vn : %s\n", lccrt_var_get_name( v));
printf( "ic : %d\n", lccrt_var_is_constarg( v));
printf( "iv : %d\n", !!v->init_value);
printf( "tp : %p\n", v->type);
printf( "tp : %p\n", lccrt_type_make_pchar( v->type->m));
printf( "ta : %d\n", v->type->type_name == LCCRT_TYPE_ARRAY);
printf( "tp : %d\n", v->type->parent == lccrt_type_make_u8( v->type->m));
printf( "ts : %d\n", v->init_value->init_type == LCCRT_VARINIT_STR);
printf( "vz : %d\n", v->init_value->init_type == LCCRT_VARINIT_ZERO);
}
lccrt_assert( lccrt_var_is_constarg_str( v));
if ( (vi->init_type == LCCRT_VARINIT_ZERO) )
{
} else if ( (vi->init_type == LCCRT_VARINIT_STR) )
{
r = vi->data.sval;
} else
{
lccrt_assert( 0);
}
return (r);
} /* lccrt_var_get_constarg_str */
/**
* Получить значение константы адреса функции.
*/
lccrt_function_ptr
lccrt_var_get_constarg_func( lccrt_var_ptr v)
{
lccrt_function_ptr r = 0;
lccrt_varinit_ptr vi = v->init_value;
lccrt_assert( lccrt_var_is_constarg_addr_func( v));
if ( (vi->init_type == LCCRT_VARINIT_ADDR_FUNC) )
{
r = vi->data.func;
} else
{
lccrt_assert( vi->init_type == LCCRT_VARINIT_ZERO);
}
return (r);
} /* lccrt_var_get_constarg_func */
/**
* Добавить в переменную новые мета-данные, либо изменить значение старых.
*/
void
lccrt_var_set_einfo( lccrt_var_ptr v, lccrt_einfo_category_t ecat, lccrt_eir_t value)
{
lccrt_module_ptr m = lccrt_var_get_module( v);
lccrt_check_type_assert( v, lccrt_var_t);
lccrt_assert( !lccrt_einfo_is_scalar( value));
v->einfo = lccrt_einfo_link_push_value( m, v->einfo, ecat, value);
return;
} /* lccrt_var_set_einfo */
/**
* Получить значение мета-данных с заданным именем или 0, если таких данных нет.
*/
lccrt_einfo_reference_t
lccrt_var_get_einfo( lccrt_var_ptr v, lccrt_einfo_category_t ecat)
{
lccrt_einfo_link_ptr unit = lccrt_einfo_link_find( v->einfo, ecat);
lccrt_einfo_reference_t r = lccrt_einfo_link_get_value( unit);
lccrt_check_type_assert( v, lccrt_var_t);
return (r);
} /* lccrt_var_get_einfo */