1608 lines
40 KiB
C
1608 lines
40 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_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 */
|