453 lines
13 KiB
C
453 lines
13 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_module.c - реализация пользовательский интерфейс (динамической) компиляции.
|
||
*/
|
||
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <ctype.h>
|
||
#include <stdarg.h>
|
||
|
||
#include "lccrt_real.h"
|
||
|
||
/**
|
||
* Инициализация контекста (стандартные типы).
|
||
*/
|
||
static void
|
||
lccrt_module_init_types_std( lccrt_module_ptr m)
|
||
{
|
||
lccrt_types_std_t *ts = &(m->types_std);
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
ts->ptr_bytesize = m->is_ptr32 ? 4 : 8;
|
||
ts->bool_type = lccrt_type_make_simple( m, LCCRT_TYPE_BOOL, "bool", 0, 1, 1);
|
||
//ts->bool_type = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "u8", 0, 1);
|
||
ts->void_type = lccrt_type_make_simple( m, LCCRT_TYPE_VOID, "void", 0, 1, 0);
|
||
ts->int_types[0][0] = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "u8", 0, 1, 1);
|
||
ts->int_types[0][1] = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "u16", 0, 2, 2);
|
||
ts->int_types[0][2] = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "u32", 0, 4, 4);
|
||
ts->int_types[0][3] = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "u64", 0, 8, 8);
|
||
ts->int_types[0][4] = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "u128", 0, 16, 16);
|
||
ts->int_types[0][5] = 0;
|
||
ts->int_types[1][0] = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "i8", 1, 1, 1);
|
||
ts->int_types[1][1] = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "i16", 1, 2, 2);
|
||
ts->int_types[1][2] = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "i32", 1, 4, 4);
|
||
ts->int_types[1][3] = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "i64", 1, 8, 8);
|
||
ts->int_types[1][4] = lccrt_type_make_simple( m, LCCRT_TYPE_INT, "i128", 1, 16, 16);
|
||
ts->int_types[1][5] = 0;
|
||
ts->float_types[0] = lccrt_type_make_simple( m, LCCRT_TYPE_FLOAT, "f32", 0, 4, 4);
|
||
ts->float_types[1] = lccrt_type_make_simple( m, LCCRT_TYPE_FLOAT, "f64", 0, 8, 8);
|
||
ts->float_types[2] = lccrt_type_make_simple( m, LCCRT_TYPE_FLOAT, "f80", 0, 16, 10);
|
||
ts->float_types[3] = lccrt_type_make_simple( m, LCCRT_TYPE_FLOAT, "f128", 0, 16, 16);
|
||
ts->float_types[4] = 0;
|
||
ts->ellipsis = lccrt_type_make_simple( m, LCCRT_TYPE_ELLIPSIS, "...", 0, 1, 0);
|
||
ts->intptr = ts->int_types[0][m->is_ptr32 ? LCCRT_INT_SUBTYPE_32 : LCCRT_INT_SUBTYPE_64];
|
||
ts->ptr_byte = lccrt_type_make_ptr_type( ts->int_types[0][LCCRT_INT_SUBTYPE_8]);
|
||
ts->ptr_char = lccrt_type_make_ptr_type( ts->int_types[1][LCCRT_INT_SUBTYPE_8]);
|
||
ts->ptr_intptr = lccrt_type_make_ptr_type( ts->intptr);
|
||
|
||
return;
|
||
} /* lccrt_module_init_types_std */
|
||
|
||
/**
|
||
* Создание нового модуля.
|
||
*/
|
||
lccrt_module_ptr
|
||
lccrt_module_new( lccrt_context_ptr ctx, const char *name, int is_m32)
|
||
{
|
||
lccrt_module_ptr m = lccrt_ctx_malloc( ctx, lccrt_module_t);
|
||
|
||
lccrt_check_type_assert( ctx, lccrt_context_t);
|
||
memset( m, 0, sizeof( m[0]));
|
||
lccrt_check_type_init( m, lccrt_module_t);
|
||
m->ctx = ctx;
|
||
m->name = lccrt_ctx_copy_str( ctx, name);
|
||
m->is_ptr32 = is_m32;
|
||
m->types = lccrt_hash_new( ctx, LCCRT_HASH_KEY_STRING);
|
||
m->type_usr_names = lccrt_hash_new( ctx, LCCRT_HASH_KEY_STRING);
|
||
m->type_max = 0;
|
||
m->gvars = lccrt_hash_new( ctx, LCCRT_HASH_KEY_STRING);
|
||
m->funcs = lccrt_hash_new( ctx, LCCRT_HASH_KEY_STRING);
|
||
m->einfo_cats = lccrt_hash_new( ctx, LCCRT_HASH_KEY_STRING);
|
||
m->einfo_tyarrs = lccrt_hash_new( ctx, LCCRT_HASH_KEY_INTPTR);
|
||
m->einfo_tysts = lccrt_hash_new( ctx, LCCRT_HASH_KEY_STRING);
|
||
lccrt_ilist_head_init( &(m->types_head));
|
||
lccrt_ilist_head_init( &(m->gvars_head));
|
||
lccrt_ilist_head_init( &(m->funcs_head));
|
||
lccrt_ilist_head_init( &(m->varinits_head));
|
||
ctx->module_max++;
|
||
m->ident_num = ctx->module_max;
|
||
m->gvars_num = 0;
|
||
m->funcs_num = 0;
|
||
m->cargs_name_id = 0;
|
||
m->global_name_id = 0;
|
||
lccrt_hash_push( ctx->modules, (uintptr_t)m, 0);
|
||
lccrt_module_init_types_std( m);
|
||
|
||
return (m);
|
||
} /* lccrt_module_new */
|
||
|
||
/**
|
||
* Удаление модуля.
|
||
*/
|
||
void
|
||
lccrt_module_delete_data( lccrt_m_ptr m)
|
||
{
|
||
lccrt_varinit_ptr vi_unit;
|
||
lccrt_einfo_block_ptr eib_unit, eib_next;
|
||
lccrt_einfo_tydescr_ptr eitd_unit, eitd_next;
|
||
lccrt_hash_entry_ptr e = 0;
|
||
lccrt_context_ptr ctx = m->ctx;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
lccrt_ctx_free( ctx, m->name);
|
||
lccrt_ctx_free( ctx, m->asm_text);
|
||
|
||
/* Удаляем все ранее созданные типы и сопутствующие структуры данных. */
|
||
for ( e = lccrt_hash_first( m->funcs); e; e = lccrt_hash_next( e) )
|
||
{
|
||
lccrt_function_delete( (lccrt_f_ptr)lccrt_hash_get( e));
|
||
}
|
||
|
||
lccrt_hash_delete( m->funcs);
|
||
|
||
for ( e = lccrt_hash_first( m->gvars); e; e = lccrt_hash_next( e) )
|
||
{
|
||
lccrt_var_delete( (lccrt_v_ptr)lccrt_hash_get( e));
|
||
}
|
||
|
||
lccrt_hash_delete( m->gvars);
|
||
|
||
for ( vi_unit = m->varinits_head.first; vi_unit; vi_unit = m->varinits_head.first )
|
||
{
|
||
lccrt_varinit_delete( vi_unit);
|
||
}
|
||
|
||
/* Удаляем цепочку привязку к модулю собственных мета-данных. */
|
||
m->einfo = lccrt_einfo_link_delete_chain( m->einfo);
|
||
|
||
/* Удаляем все категории мета-данных. */
|
||
lccrt_hash_delete( m->einfo_cats);
|
||
|
||
/* Удаляем все мета-данные. */
|
||
for ( eib_unit = m->eblocks_head; eib_unit; eib_unit = eib_next )
|
||
{
|
||
eib_next = eib_unit->next;
|
||
lccrt_einfo_block_delete( eib_unit);
|
||
}
|
||
|
||
/* Удаляем все описания типов мета-данных. */
|
||
for ( eitd_unit = m->etydescrs_head; eitd_unit; eitd_unit = eitd_next )
|
||
{
|
||
eitd_next = eitd_unit->next;
|
||
lccrt_einfo_tydescr_delete( eitd_unit);
|
||
}
|
||
|
||
/* Удаляем таблицы хеширования описания мета-данных. */
|
||
lccrt_hash_delete( m->einfo_tyarrs);
|
||
lccrt_hash_delete( m->einfo_tysts);
|
||
|
||
for ( e = lccrt_hash_first( m->types); e; e = lccrt_hash_next( e) )
|
||
{
|
||
lccrt_type_delete( (lccrt_t_ptr)lccrt_hash_get( e));
|
||
}
|
||
|
||
lccrt_hash_delete( m->types);
|
||
lccrt_hash_delete( m->type_usr_names);
|
||
|
||
lccrt_check_type_done( m, lccrt_module_t);
|
||
lccrt_ctx_free( ctx, m);
|
||
|
||
return;
|
||
} /* lccrt_module_delete_data */
|
||
|
||
/**
|
||
* Удаление модуля.
|
||
*/
|
||
void
|
||
lccrt_module_delete( lccrt_module_ptr m)
|
||
{
|
||
lccrt_context_ptr ctx = m->ctx;
|
||
lccrt_hash_entry_ptr he = lccrt_hash_find( ctx->modules, (uintptr_t)m);
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
lccrt_check_type_assert( ctx, lccrt_context_t);
|
||
lccrt_module_delete_data( m);
|
||
if ( he )
|
||
{
|
||
lccrt_hash_remove( he);
|
||
}
|
||
|
||
return;
|
||
} /* lccrt_module_delete */
|
||
|
||
/**
|
||
* Прочитать поле.
|
||
*/
|
||
lccrt_context_ptr
|
||
lccrt_module_get_context( lccrt_module_ptr m)
|
||
{
|
||
lccrt_context_ptr r = m->ctx;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (r);
|
||
} /* lccrt_module_get_context */
|
||
|
||
/**
|
||
* Прочитать поле.
|
||
*/
|
||
const char *
|
||
lccrt_module_get_inline_asm( lccrt_m_ptr m)
|
||
{
|
||
const char *r = m->asm_text;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (r);
|
||
} /* lccrt_module_get_inline_asm */
|
||
|
||
/**
|
||
* Прочитать поле.
|
||
*/
|
||
void
|
||
lccrt_module_set_inline_asm( lccrt_m_ptr m, const char *asm_text)
|
||
{
|
||
lccrt_ctx_ptr ctx = m->ctx;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
lccrt_ctx_free( ctx, m->asm_text);
|
||
m->asm_text = lccrt_ctx_copy_str( ctx, asm_text);
|
||
|
||
return;
|
||
} /* lccrt_module_set_inline_asm */
|
||
|
||
/**
|
||
* Прочитать поле.
|
||
*/
|
||
uint64_t
|
||
lccrt_module_get_type_max( lccrt_module_ptr m)
|
||
{
|
||
uint64_t r = m->type_max;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (r);
|
||
} /* lccrt_module_get_type_max */
|
||
|
||
/**
|
||
* Прочитать поле.
|
||
*/
|
||
uint64_t
|
||
lccrt_module_get_func_max( lccrt_module_ptr m)
|
||
{
|
||
uint64_t r = m->funcs_num;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (r);
|
||
} /* lccrt_module_get_func_max */
|
||
|
||
/**
|
||
* Прочитать поле.
|
||
*/
|
||
const char*
|
||
lccrt_module_get_name( lccrt_module_ptr m)
|
||
{
|
||
const char *r = m->name;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (r);
|
||
} /* lccrt_module_get_name */
|
||
|
||
/**
|
||
* Формирование нового имени для глобальной переменной.
|
||
*/
|
||
char *
|
||
lccrt_module_name_new_global( lccrt_m_ptr module, const char *name)
|
||
{
|
||
char str[1024];
|
||
const char *q = name;
|
||
char *result = 0;
|
||
|
||
lccrt_check_type_assert( module, lccrt_module_t);
|
||
if ( !name )
|
||
{
|
||
snprintf( str, 1024, "__lccrt_g%jd", module->global_name_id);
|
||
module->global_name_id++;
|
||
q = str;
|
||
}
|
||
|
||
result = lccrt_ctx_copy_str( module->ctx, q);
|
||
|
||
return (result);
|
||
} /* lccrt_module_name_new_global */
|
||
|
||
/**
|
||
* Прочитать поле.
|
||
*/
|
||
int
|
||
lccrt_module_is_ptr32( lccrt_module_ptr m)
|
||
{
|
||
int r = m->is_ptr32;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (r);
|
||
} /* lccrt_module_is_ptr32 */
|
||
|
||
/**
|
||
* Прочитать поле.
|
||
*/
|
||
lccrt_hash_ptr
|
||
lccrt_module_get_types( lccrt_module_ptr m)
|
||
{
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (m->types);
|
||
} /* lccrt_module_get_types */
|
||
|
||
/**
|
||
* Прочитать поле.
|
||
*/
|
||
lccrt_hash_ptr
|
||
lccrt_module_get_gvars( lccrt_module_ptr m)
|
||
{
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (m->gvars);
|
||
} /* lccrt_module_get_gvars */
|
||
|
||
/**
|
||
* Прочитать поле.
|
||
*/
|
||
lccrt_hash_ptr
|
||
lccrt_module_get_funcs( lccrt_module_ptr m)
|
||
{
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (m->funcs);
|
||
} /* lccrt_module_get_funcs */
|
||
|
||
/**
|
||
* Получить первый тип модуля.
|
||
*/
|
||
lccrt_type_ptr
|
||
lccrt_module_get_first_type( lccrt_module_ptr m)
|
||
{
|
||
lccrt_type_ptr r;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
r = m->types_head.first;
|
||
lccrt_check_type_assert( r, lccrt_type_t);
|
||
|
||
return (r);
|
||
} /* lccrt_module_get_first_type */
|
||
|
||
/**
|
||
* Получить первую глобальную переменную модуля.
|
||
*/
|
||
lccrt_var_ptr
|
||
lccrt_module_get_first_var( lccrt_module_ptr m)
|
||
{
|
||
lccrt_var_ptr r;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
r = m->gvars_head.first;
|
||
lccrt_assert( !r || lccrt_var_is_global( r));
|
||
|
||
return (r);
|
||
} /* lccrt_module_get_first_var */
|
||
|
||
/**
|
||
* Получить первую глобальную переменную модуля.
|
||
*/
|
||
lccrt_function_ptr
|
||
lccrt_module_get_first_func( lccrt_module_ptr m)
|
||
{
|
||
lccrt_function_ptr r;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
r = m->funcs_head.first;
|
||
|
||
return (r);
|
||
} /* lccrt_module_get_first_func */
|
||
|
||
/**
|
||
* Поиск функции по имени.
|
||
*/
|
||
lccrt_function_ptr
|
||
lccrt_module_find_function( lccrt_module_ptr m, const char *name)
|
||
{
|
||
lccrt_hash_entry_ptr e = lccrt_hash_find( m->funcs, (uintptr_t)name);
|
||
lccrt_function_ptr r = e ? (lccrt_f_ptr)lccrt_hash_get( e) : 0;
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (r);
|
||
} /* lccrt_module_find_function */
|
||
|
||
/**
|
||
* Добавить в модуль новые мета-данные, либо изменить значение старых.
|
||
*/
|
||
void
|
||
lccrt_module_set_einfo( lccrt_module_ptr m, lccrt_einfo_category_t ecat, lccrt_eir_t value)
|
||
{
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
lccrt_assert( !lccrt_einfo_is_scalar( value));
|
||
m->einfo = lccrt_einfo_link_push_value( m, m->einfo, ecat, value);
|
||
|
||
return;
|
||
} /* lccrt_module_set_einfo */
|
||
|
||
/**
|
||
* Получить значение мета-данных с заданным именем или 0, если таких данных нет.
|
||
*/
|
||
lccrt_einfo_reference_t
|
||
lccrt_module_get_einfo( lccrt_module_ptr m, lccrt_einfo_category_t ecat)
|
||
{
|
||
lccrt_einfo_link_ptr unit = lccrt_einfo_link_find( m->einfo, ecat);
|
||
lccrt_einfo_reference_t r = lccrt_einfo_link_get_value( unit);
|
||
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
|
||
return (r);
|
||
} /* lccrt_module_get_einfo */
|
||
|
||
/**
|
||
* Получить первую глобальную переменную модуля.
|
||
*/
|
||
void
|
||
lccrt_module_rename( lccrt_module_ptr m, const char *new_name)
|
||
{
|
||
lccrt_check_type_assert( m, lccrt_module_t);
|
||
lccrt_assert( 0);
|
||
|
||
return;
|
||
} /* lccrt_module_rename */
|
||
|
||
/**
|
||
* Всем типам, у которых не задано пользовательское имя, назначить пользовательское имя.
|
||
*/
|
||
void
|
||
lccrt_module_init_types_usr_names( lccrt_module_ptr m)
|
||
{
|
||
lccrt_hash_entry_ptr e;
|
||
|
||
for ( e = lccrt_hash_first( m->types); e; e = lccrt_hash_next( e) )
|
||
{
|
||
lccrt_type_ptr t = (lccrt_type_ptr)(uintptr_t)lccrt_hash_get( e);
|
||
|
||
if ( t->usr_name )
|
||
{
|
||
}
|
||
}
|
||
|
||
return;
|
||
} /* lccrt_module_init_types_usr_names */
|