lccrt/lib/irv/lccrt_func.c

1242 lines
34 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_func.c - реализация пользовательский интерфейс (динамической) компиляции.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "lccrt_irv.h"
#include "lccrt_jit.h"
typedef enum
{
LCCRT_FCT_COPY, /* полное копирование функции (возможно в другой модуль) */
LCCRT_FCT_INLINE, /* встраивание функции (в рамках одного модуля) */
LCCRT_FCT_LAST
} lccrt_function_copy_type_t;
/**
* Данные, используемые при копировании функции.
*/
typedef struct
{
lccrt_function_copy_type_t type; /* тип копирования */
lccrt_function_ptr src_func; /* исходная функция */
lccrt_function_ptr dst_func; /* результирующая функция */
lccrt_hash_ptr vars; /* соответствие (src_var -> dst_var) */
lccrt_hash_ptr opers; /* соответствие (src_oper -> dst_oper) */
lccrt_hash_ptr types; /* соответствие (src_type -> dst_type) */
lccrt_oper_ptr call; /* операция вызова (для LCCRT_FCT_INLINE) */
} lccrt_function_copy_info_t;
extern int lccrt_function_set_attr( lccrt_f_ptr f, lccrt_function_attr_name_t attr, int value);
static int lccrt_function_get_attr( lccrt_f_ptr f, lccrt_function_attr_name_t attr);
/**
* Создание новой функции.
*/
lccrt_function_ptr
lccrt_function_new( lccrt_module_ptr module, lccrt_type_ptr sig,
const char *name, const char *asm_name, lccrt_link_t vlink,
int is_declaration, int is_builtin)
{
int k;
int is_fnew = 0;
lccrt_context_ptr ctx = module->ctx;
lccrt_function_ptr f = 0;
lccrt_hash_entry_ptr entry = 0;
lccrt_asmlink_t link = lccrt_link_unpack( vlink);
lccrt_assert( link.tls == LCCRT_LINK_TLS_NO);
lccrt_assert( !link.is_cnst);
lccrt_check_type_assert( module, lccrt_module_t);
lccrt_check_type_assert( sig, lccrt_type_t);
entry = lccrt_hash_push( module->funcs, (uintptr_t)name, &is_fnew);
if ( !is_fnew )
{
f = (lccrt_function_ptr)lccrt_hash_get( entry);
if ( (f->sig_type == sig)
&& is_declaration
&& lccrt_function_get_attr( f, LCCRT_FUNC_ATTR_DECLARATION)
&& (is_builtin == lccrt_function_get_attr( f, LCCRT_FUNC_ATTR_BUILTIN))
&& ((asm_name == f->asm_name)
|| (asm_name
&& f->asm_name
&& lccrt_str_eq( asm_name, f->asm_name)))
&& (vlink == lccrt_function_get_link( f)) )
{
} else
{
lccrt_assert( 0);
}
} else
{
f = lccrt_ctx_malloc( ctx, lccrt_function_t);
memset( f, 0, sizeof( f[0]));
lccrt_check_type_init( f, lccrt_function_t);
f->ctx = (lccrt_context_ptr)ctx;
f->module = (lccrt_module_ptr)module;
module->funcs_num++;
f->ident_num = module->funcs_num;
f->name = lccrt_ctx_copy_str( ctx, name);
f->asm_name = lccrt_ctx_copy_str( ctx, asm_name);
f->link = link;
f->sig_type = sig;
f->args = lccrt_ctx_mallocn( ctx, lccrt_var_ptr, sig->num_args);
f->sysargs = 0;
f->sysargs_num = 0;
f->lvars_num = 0;
f->opers_num = 0;
f->local_name_id = 0;
lccrt_ilist_unit_init( &(f->funcs_unit));
lccrt_ilist_head_init( &(f->lvars_head));
lccrt_check_type_init( &(f->cur), lccrt_oper_iterator_t);
f->cur.is_forward = 1;
f->lvars = lccrt_hash_new( ctx, LCCRT_HASH_KEY_STRING);
for ( k = 0; k < sig->num_args; ++k )
{
f->args[k] = 0;
}
lccrt_function_set_attr( f, LCCRT_FUNC_ATTR_DECLARATION, is_declaration);
lccrt_function_set_attr( f, LCCRT_FUNC_ATTR_BUILTIN, is_builtin);
lccrt_hash_set( entry, (uintptr_t)f);
lccrt_ilist_head_insert( &(module->funcs_head), funcs_unit, f);
}
return (f);
} /* lccrt_function_new */
/**
* Удаление функции.
*/
void
lccrt_function_delete( lccrt_function_ptr f)
{
lccrt_oper_ptr o;
lccrt_he_ptr e;
lccrt_context_ptr ctx = f->ctx;
lccrt_module_ptr m = f->module;
lccrt_oper_ptr o_next = 0;
lccrt_check_type_assert( f, lccrt_function_t);
lccrt_ilist_head_remove( &(m->funcs_head), funcs_unit, f);
lccrt_ctx_free( ctx, f->name);
lccrt_ctx_free( ctx, f->asm_name);
for ( e = lccrt_hash_first( f->lvars); e; e = lccrt_hash_next( e) )
{
lccrt_var_delete( (lccrt_var_ptr)lccrt_hash_get( e));
}
lccrt_hash_delete( f->lvars);
lccrt_ctx_free( ctx, f->sysargs);
lccrt_ctx_free( ctx, f->args);
lccrt_ctx_free( ctx, f->section);
lccrt_ctx_free( ctx, f->comdat);
/* Удаляем промежуточное представление функции. */
for ( o = f->start; o; o = o_next )
{
o_next = o->next;
o->next = 0;
if ( o_next )
{
o_next->prev = 0;
}
o->res = 0;
lccrt_oper_delete( o);
}
f->einfo = lccrt_einfo_link_delete_chain( f->einfo);
lccrt_check_type_done( f, lccrt_function_t);
lccrt_ctx_free( ctx, f);
return;
} /* lccrt_function_delete */
/**
* Заполнение в функции jit-данных.
*/
void
lccrt_function_init_jit_info( lccrt_f_ptr f, lccrt_f_ptr root,
lccrt_v_ptr func_entry, lccrt_v_ptr profgen_tls)
{
lccrt_check_type_assert( f, lccrt_function_t);
lccrt_assert( func_entry);
if ( lccrt_function_is_profgen( f) )
{
lccrt_assert( root && (f != root));
lccrt_assert( profgen_tls);
} else
{
lccrt_assert( !root);
lccrt_assert( !profgen_tls);
}
return;
} /* lccrt_function_init_jit_info */
/**
* Получить значение поля.
*/
lccrt_fji_ptr
lccrt_function_get_jit_info( lccrt_f_ptr f)
{
lccrt_fji_ptr r = 0;
lccrt_check_type_assert( f, lccrt_function_t);
return (r);
} /* lccrt_function_get_jit_info */
/**
* Получить имя функции.
*/
const char *
lccrt_function_get_name( lccrt_function_ptr func)
{
const char *r = func->name;
lccrt_check_type_assert( func, lccrt_function_t);
return (r);
} /* lccrt_function_get_name */
/**
* Получить поле.
*/
lccrt_module_ptr
lccrt_function_get_module( lccrt_function_ptr func)
{
lccrt_module_ptr r;
lccrt_check_type_assert( func, lccrt_function_t);
r = func->module;
return (r);
} /* lccrt_function_get_module */
/**
* Получить поле.
*/
lccrt_type_ptr
lccrt_function_get_type( lccrt_function_ptr func)
{
lccrt_type_ptr r;
lccrt_check_type_assert( func, lccrt_function_t);
r = func->sig_type;
lccrt_assert( lccrt_type_is_function( func->sig_type));
return (r);
} /* lccrt_function_get_type */
/**
* Проверяем, что у функции типом последнего аргумента является тип-многоточие.
*/
int
lccrt_function_is_var_arg( lccrt_function_ptr f)
{
int r = 0;
lccrt_check_type_assert( f, lccrt_function_t);
r = lccrt_type_is_function_var_arg( f->sig_type);
return (r);
} /* lccrt_function_is_var_arg */
/**
* Получить количество формальных параметров (без учета параметра "...").
*/
int
lccrt_function_get_num_args( lccrt_function_ptr f)
{
int r;
lccrt_check_type_assert( f, lccrt_function_t);
r = lccrt_type_get_num_args( f->sig_type) - lccrt_type_is_function_var_arg( f->sig_type);
lccrt_assert( r >= 0);
return (r);
} /* lccrt_function_get_num_args */
/**
* Получить количество (специальных) параметров.
*/
int
lccrt_function_get_num_sysargs( lccrt_function_ptr f)
{
int r;
lccrt_check_type_assert( f, lccrt_function_t);
r = f->sysargs_num;
lccrt_assert( r >= 0);
return (r);
} /* lccrt_function_get_num_sysargs */
/**
* Получить поле.
*/
lccrt_var_ptr
lccrt_function_get_arg( lccrt_function_ptr func, int arg_num)
{
lccrt_var_ptr r;
lccrt_check_type_assert( func, lccrt_function_t);
lccrt_assert( (0 <= arg_num) && (arg_num < lccrt_function_get_num_args( func)));
r = func->args[arg_num];
return (r);
} /* lccrt_function_get_arg */
/**
* Получить поле.
*/
lccrt_var_ptr
lccrt_function_get_sysarg( lccrt_function_ptr func, int arg_num)
{
lccrt_var_ptr r;
lccrt_check_type_assert( func, lccrt_function_t);
lccrt_assert( (0 <= arg_num) && (arg_num < lccrt_function_get_num_sysargs( func)));
r = func->sysargs[arg_num];
return (r);
} /* lccrt_function_get_sysarg */
/**
* Установить поле.
*/
void
lccrt_function_set_arg( lccrt_function_ptr func, int arg_num, lccrt_var_ptr arg)
{
lccrt_check_type_assert( func, lccrt_function_t);
lccrt_check_type_assert( arg, lccrt_var_t);
lccrt_assert( (0 <= arg_num) && (arg_num < lccrt_function_get_num_args( func)));
func->args[arg_num] = arg;
if ( arg )
{
arg->arg_num = arg_num;
lccrt_assert( lccrt_var_get_loc( arg) == LCCRT_VAR_LOC_ARG);
}
return;
} /* lccrt_function_set_arg */
/**
* Установить поле.
*/
void
lccrt_function_set_sysarg( lccrt_function_ptr func, int arg_num, lccrt_var_ptr arg)
{
lccrt_check_type_assert( func, lccrt_function_t);
lccrt_check_type_assert( arg, lccrt_var_t);
lccrt_assert( (0 <= arg_num) && (arg_num < lccrt_function_get_num_sysargs( func)));
func->sysargs[arg_num] = arg;
if ( arg )
{
arg->arg_num = arg_num;
lccrt_assert( lccrt_var_get_loc( arg) == LCCRT_VAR_LOC_SYSARG);
}
return;
} /* lccrt_function_set_sysarg */
/**
* Установить поле.
*/
void
lccrt_function_add_arg( lccrt_function_ptr func, int arg_num, lccrt_var_ptr arg)
{
int k;
lccrt_module_ptr m = lccrt_function_get_module( func);
lccrt_context_ptr ctx = lccrt_module_get_context( m);
int num_args = lccrt_function_get_num_args( func);
lccrt_type_ptr *types = lccrt_ctx_mallocn( ctx, lccrt_type_ptr, num_args + 1);
lccrt_var_ptr *args = lccrt_ctx_mallocn( ctx, lccrt_var_ptr, num_args + 1);
lccrt_type_ptr ftype = lccrt_function_get_type( func);
lccrt_check_type_assert( func, lccrt_function_t);
lccrt_check_type_assert( arg, lccrt_var_t);
lccrt_assert( (0 <= arg_num) && (arg_num == num_args));
types[arg_num] = lccrt_var_get_type( arg);
for ( k = 0; k < arg_num; ++k )
{
types[k] = lccrt_type_get_arg( ftype, k);
}
ftype = lccrt_type_make_func( lccrt_type_get_parent( ftype), arg_num + 1, types);
lccrt_ctx_free( ctx, types);
func->sig_type = ftype;
memset( args + num_args, 0, sizeof( args[0]));
memcpy( args, func->args, num_args*sizeof( args[0]));
lccrt_ctx_free( ctx, func->args);
func->args = args;
lccrt_function_set_arg( func, arg_num, arg);
return;
} /* lccrt_function_add_arg */
/**
* Добавить (с конца) новый (специальный) параметр.
*/
void
lccrt_function_add_sysarg( lccrt_function_ptr func, int arg_num, lccrt_var_ptr arg)
{
int k;
lccrt_module_ptr m = lccrt_function_get_module( func);
lccrt_context_ptr ctx = lccrt_module_get_context( m);
int num_args = lccrt_function_get_num_sysargs( func);
lccrt_var_ptr *args = lccrt_ctx_mallocn( ctx, lccrt_var_ptr, num_args + 1);
lccrt_type_ptr ftype = lccrt_function_get_type( func);
lccrt_check_type_assert( func, lccrt_function_t);
lccrt_check_type_assert( arg, lccrt_var_t);
lccrt_assert( (0 <= arg_num) && (arg_num == num_args));
memset( args + num_args, 0, sizeof( args[0]));
memcpy( args, func->sysargs, num_args*sizeof( args[0]));
lccrt_ctx_free( ctx, func->sysargs);
func->sysargs = args;
func->sysargs_num++;
lccrt_function_set_sysarg( func, arg_num, arg);
return;
} /* lccrt_function_add_sysarg */
/**
* Получить поле.
*/
const char *
lccrt_function_get_asm_name( lccrt_function_ptr func)
{
const char *r;
lccrt_check_type_assert( func, lccrt_function_t);
r = func->asm_name;
return (r);
} /* lccrt_function_get_asm_name */
/**
* Получить поле.
*/
const char *
lccrt_function_get_section( lccrt_function_ptr func)
{
const char *r;
lccrt_check_type_assert( func, lccrt_function_t);
r = func->section;
return (r);
} /* lccrt_function_get_section */
/**
* Получить поле.
*/
const char *
lccrt_function_get_comdat( lccrt_function_ptr func)
{
const char *r;
lccrt_check_type_assert( func, lccrt_function_t);
r = func->comdat;
return (r);
} /* lccrt_function_get_comdat */
/**
* Установить значение поля.
*/
lccrt_link_t
lccrt_function_get_link( lccrt_function_ptr func)
{
lccrt_link_t r;
lccrt_check_type_assert( func, lccrt_function_t);
r = lccrt_link_conv( func->link);
return (r);
} /* lccrt_function_get_link */
/**
* Установить значение поля.
*/
void
lccrt_function_set_link( lccrt_function_ptr func, lccrt_link_t link)
{
lccrt_check_type_assert( func, lccrt_function_t);
func->link = lccrt_link_unpack( link);
return;
} /* lccrt_function_set_link */
/**
* Установить значение поля.
*/
void
lccrt_function_set_section( lccrt_function_ptr func, const char *section)
{
lccrt_context_ptr ctx = func->ctx;
lccrt_check_type_assert( func, lccrt_function_t);
lccrt_assert( !func->section);
func->section = lccrt_ctx_copy_str( ctx, section);
return;
} /* lccrt_function_set_section */
/**
* Установить значение поля.
*/
void
lccrt_function_set_comdat( lccrt_function_ptr func, const char *comdat)
{
lccrt_context_ptr ctx = func->ctx;
lccrt_check_type_assert( func, lccrt_function_t);
lccrt_assert( !func->comdat);
func->comdat = lccrt_ctx_copy_str( ctx, comdat);
return;
} /* lccrt_function_set_comdat */
/**
* Получить поле.
*/
lccrt_oper_ptr
lccrt_function_get_first_oper( lccrt_function_ptr func)
{
lccrt_oper_ptr r;
lccrt_check_type_assert( func, lccrt_function_t);
r = func->start;
return (r);
} /* lccrt_function_get_first_oper */
/**
* Получить поле.
*/
lccrt_var_ptr
lccrt_function_get_first_var( lccrt_function_ptr func)
{
lccrt_var_ptr r;
lccrt_check_type_assert( func, lccrt_function_t);
r = func->lvars_head.first;
lccrt_assert( !r || lccrt_var_is_local( r));
return (r);
} /* lccrt_function_get_first_var */
/**
* Получить поле.
*/
lccrt_function_init_type_t
lccrt_function_get_init_type( lccrt_function_ptr func)
{
lccrt_function_init_type_t r;
lccrt_check_type_assert( func, lccrt_function_t);
r = func->init_type;
return (r);
} /* lccrt_function_get_init_type */
/**
* Установить для функции значение атрибута.
*/
void
lccrt_function_set_init_priority( lccrt_f_ptr f, int value)
{
lccrt_check_type_assert( f, lccrt_function_t);
f->init_priority = value;
return;
} /* lccrt_function_set_init_priority */
/**
* Получить поле.
*/
int
lccrt_function_get_init_priority( lccrt_function_ptr func)
{
int r;
lccrt_check_type_assert( func, lccrt_function_t);
r = func->init_priority;
return (r);
} /* lccrt_function_get_init_priority */
/**
* Установить для функции значение атрибута.
*/
void
lccrt_function_set_init_type( lccrt_f_ptr f, lccrt_function_init_type_t value)
{
lccrt_check_type_assert( f, lccrt_function_t);
f->init_type = value;
return;
} /* lccrt_function_set_init_type */
/**
* Получить поле.
*/
lccrt_function_ptr
lccrt_function_get_next_func( lccrt_function_ptr func)
{
lccrt_function_ptr r;
lccrt_check_type_assert( func, lccrt_function_t);
r = func->funcs_unit.next;
return (r);
} /* lccrt_function_get_next_func */
/**
* Получить для функции значение атрибута.
*/
static int
lccrt_function_get_attr( lccrt_f_ptr f, lccrt_function_attr_name_t attr)
{
int r;
int k = attr / 64;
int j = attr % 64;
r = (f->attrs[k] >> j) & 0x1;
return (r);
} /* lccrt_function_get_attr */
/**
* Установить для функции значение атрибута.
*/
int
lccrt_function_set_attr( lccrt_f_ptr f, lccrt_function_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_function_get_attr( f, attr);
f->attrs[k] = (f->attrs[k] & (~bit)) | value_bit;
return (r);
} /* lccrt_function_set_attr */
/**
* Скопировать значение булевых атрибутов.
*/
static void
lccrt_function_copy_attrs( lccrt_f_ptr dst, lccrt_f_ptr src)
{
int i;
for ( i = 0; i < LCCRT_FUNC_ATTRS_LENGTH; ++i )
{
dst->attrs[i] = src->attrs[i];
}
return;
} /* lccrt_function_copy_attrs */
/**
* Получить для функции значение атрибута.
*/
int
lccrt_function_get_attr_does_not_throw( lccrt_f_ptr f)
{
int r = lccrt_function_get_attr( f, LCCRT_FUNC_ATTR_DOES_NOT_THROW);
return (r);
} /* lccrt_function_get_attr_does_not_throw */
/**
* Установить для функции значение атрибута.
*/
int
lccrt_function_set_attr_does_not_throw( lccrt_f_ptr f, int value)
{
int r = lccrt_function_set_attr( f, LCCRT_FUNC_ATTR_DOES_NOT_THROW, value);
return (r);
} /* lccrt_function_set_attr_does_not_throw */
/**
* Получить для функции значение атрибута.
*/
int
lccrt_function_get_attr_extern_inline( lccrt_f_ptr f)
{
int r = lccrt_function_get_attr( f, LCCRT_FUNC_ATTR_EXTERN_INLINE);
return (r);
} /* lccrt_function_get_attr_extern_inline */
/**
* Установить для функции значение атрибута.
*/
int
lccrt_function_set_attr_extern_inline( lccrt_f_ptr f, int value)
{
int r = lccrt_function_set_attr( f, LCCRT_FUNC_ATTR_EXTERN_INLINE, value);
return (r);
} /* lccrt_function_set_attr_extern_inline */
/**
* Получить для функции значение атрибута.
*/
int
lccrt_function_get_attr_used( lccrt_f_ptr f)
{
int r = lccrt_function_get_attr( f, LCCRT_FUNC_ATTR_USED);
return (r);
} /* lccrt_function_get_attr_used */
/**
* Установить для функции значение атрибута.
*/
int
lccrt_function_set_attr_used( lccrt_f_ptr f, int value)
{
int r = lccrt_function_set_attr( f, LCCRT_FUNC_ATTR_USED, value);
return (r);
} /* lccrt_function_set_attr_used */
/**
* Установить для функции значение поля.
*/
int
lccrt_function_set_declaration( lccrt_f_ptr f, int value)
{
int r = lccrt_function_set_attr( f, LCCRT_FUNC_ATTR_DECLARATION, value);
return (r);
} /* lccrt_function_set_declaration */
/**
* Установить для функции значение атрибута.
*/
int
lccrt_function_get_attr_jit_profgen( lccrt_f_ptr f)
{
int r = lccrt_function_get_attr( f, LCCRT_FUNC_ATTR_JIT_PROFGEN);
return (r);
} /* lccrt_function_get_attr_jit_profgen */
/**
* Установить для функции значение атрибута.
*/
int
lccrt_function_set_attr_jit_profgen( lccrt_f_ptr f, int value)
{
int r = lccrt_function_set_attr( f, LCCRT_FUNC_ATTR_JIT_PROFGEN, value);
return (r);
} /* lccrt_function_set_attr_jit_profgen */
/**
* Получить для функции значение атрибута.
*/
int
lccrt_function_is_declaration( lccrt_f_ptr f)
{
int r = lccrt_function_get_attr( f, LCCRT_FUNC_ATTR_DECLARATION);
return (r);
} /* lccrt_function_is_declaration */
/**
* Получить для функции значение атрибута.
*/
int
lccrt_function_is_builtin( lccrt_f_ptr f)
{
int r = lccrt_function_get_attr( f, LCCRT_FUNC_ATTR_BUILTIN);
return (r);
} /* lccrt_function_is_builtin */
/**
* Получить для функции значение атрибута.
*/
int
lccrt_function_is_used( lccrt_f_ptr f)
{
int r = lccrt_function_get_attr( f, LCCRT_FUNC_ATTR_USED);
return (r);
} /* lccrt_function_is_used */
/**
* Получить для функции значение атрибута.
*/
int
lccrt_function_is_profgen( lccrt_f_ptr f)
{
int r = lccrt_function_get_attr( f, LCCRT_FUNC_ATTR_JIT_PROFGEN);
return (r);
} /* lccrt_function_is_profgen */
/**
* Формирование нового имени для локальной переменной.
*/
char *
lccrt_function_name_new_local( lccrt_f_ptr func, const char *name)
{
char *result = 0;
lccrt_context_ptr ctx = func->ctx;
lccrt_check_type_assert( func, lccrt_function_t);
if ( name )
{
result = lccrt_ctx_copy_str( ctx, name);
} else
{
char str[1024];
snprintf( str, 1024, "__lccrt_l%d", func->local_name_id);
func->local_name_id++;
result = lccrt_ctx_copy_str( ctx, str);
}
return (result);
} /* lccrt_function_name_new_local */
/**
* Подготовка данных.
*/
static void
lccrt_function_copy_info_init( lccrt_function_copy_info_t *fci, lccrt_function_copy_type_t type,
lccrt_f_ptr src_func, lccrt_f_ptr dst_func, lccrt_hash_ptr types,
lccrt_o_ptr call)
{
memset( fci, 0, sizeof( fci[0]));
fci->type = type;
fci->src_func = src_func;
fci->dst_func = dst_func;
fci->vars = lccrt_hash_new( src_func->ctx, LCCRT_HASH_KEY_INTPTR);
fci->opers = lccrt_hash_new( src_func->ctx, LCCRT_HASH_KEY_INTPTR);
fci->types = types;
fci->call = call;
return;
} /* lccrt_function_copy_info_init */
/**
* Освобождение данных.
*/
static void
lccrt_function_copy_info_done( lccrt_function_copy_info_t *fci)
{
lccrt_hash_delete( fci->opers);
lccrt_hash_delete( fci->vars);
return;
} /* lccrt_function_copy_info_done */
/**
* Создание копии локальной переменной в новой функции.
*/
lccrt_var_ptr
lccrt_function_var_import( lccrt_f_ptr dst_func, lccrt_f_ptr src_func, lccrt_v_ptr v,
lccrt_h_ptr vars, lccrt_hash_ptr types, int is_same_name)
{
lccrt_he_ptr e;
lccrt_var_ptr r = 0;
lccrt_type_ptr type = 0;
lccrt_link_t ln = lccrt_link_conv( v->link);
e = vars ? lccrt_hash_find( vars, (uintptr_t)v) : 0;
r = e ? (lccrt_var_ptr)lccrt_hash_get( e) : 0;
if ( !r )
{
const char *new_name = is_same_name ? v->name : 0;
type = lccrt_type_import( lccrt_function_get_module( dst_func), v->type, types);
//r = lccrt_var_new( dst_func, v->loc, type, v->name, v->asm_name, ln, v->align);
r = lccrt_var_new( dst_func, v->loc, type, new_name, v->asm_name, ln, v->align);
r->arg_num = v->arg_num;
lccrt_var_copy_attrs( r, v);
lccrt_assert( !v->init_value);
if ( v->loc == LCCRT_VAR_LOC_ARG )
{
lccrt_function_set_arg( dst_func, v->arg_num, r);
} else if ( v->loc == LCCRT_VAR_LOC_SYSARG )
{
lccrt_function_set_sysarg( dst_func, v->arg_num, r);
} else if ( (v->loc == LCCRT_VAR_LOC_LOCAL)
|| (v->loc == LCCRT_VAR_LOC_ASM) )
{
} else
{
lccrt_assert( 0);
}
if ( vars )
{
e = lccrt_hash_push( vars, (uintptr_t)v, 0);
lccrt_hash_set( e, (uintptr_t)r);
}
}
return (r);
} /* lccrt_function_var_import */
/**
* Создание копии операции из другой функции (при копировании функции).
*/
static lccrt_oper_ptr
lccrt_function_oper_import( lccrt_function_copy_info_t *fci, lccrt_o_ptr op, lccrt_oi_ptr it)
{
int k;
lccrt_he_ptr e;
lccrt_oper_ptr r = 0;
lccrt_var_ptr res = 0;
lccrt_function_ptr dst_func = fci->dst_func;
lccrt_module_ptr dst_m = lccrt_function_get_module( dst_func);
lccrt_context_ptr dst_ctx = lccrt_module_get_context( dst_m);
if ( op->res )
{
if ( lccrt_var_is_global( op->res) )
{
res = op->res;
} else
{
e = lccrt_hash_find( fci->vars, (uintptr_t)op->res);
res = e ? (lccrt_var_ptr)lccrt_hash_get( e) : 0;
lccrt_assert( res);
}
}
r = lccrt_oper_new( fci->dst_func, op->name, 0, op->num_args, op->args,
op->num_sysargs, res, it);
r->ident_num = op->ident_num;
r->is_volatile = op->is_volatile;
r->is_atomic = op->is_atomic;
for ( k = 0; k < r->num_args; ++k )
{
if ( lccrt_oper_name_is_arg_var( r->name, k) )
{
lccrt_var_ptr v = op->args[k].v;
if ( lccrt_var_is_global( v) )
{
if ( (fci->type == LCCRT_FCT_INLINE)
&& lccrt_oper_is_label( r) )
{
char *new_name = lccrt_function_name_new_local( fci->dst_func, 0);
int new_len = strlen( new_name);
r->args[k].v = lccrt_var_new_constarg_str( dst_m, new_len + 1, new_name);
lccrt_ctx_free( dst_ctx, new_name);
} else
{
r->args[k].v = v;
}
} else
{
e = lccrt_hash_find( fci->vars, (uintptr_t)v);
r->args[k].v = e ? (lccrt_var_ptr)lccrt_hash_get( e) : 0;
lccrt_assert( !v || r->args[k].v);
}
} else
{
e = lccrt_hash_find( fci->opers, (uintptr_t)op->args[k].op);
r->args[k].op = e ? (lccrt_oper_ptr)lccrt_hash_get( e) : 0;
lccrt_assert( !op->args[k].op || r->args[k].op);
}
}
e = lccrt_hash_push( fci->opers, (uintptr_t)op, 0);
lccrt_hash_set( e, (uintptr_t)r);
return (r);
} /* lccrt_function_oper_import */
/**
* Удаление кода функции (локальных переменных и операций).
*/
void
lccrt_function_clear( lccrt_function_ptr f)
{
lccrt_he_ptr e;
lccrt_oper_ptr o, o_next;
/* Удаляем промежуточное представление функции. */
for ( o = f->start; o; o = o_next )
{
o_next = o->next;
o->next = 0;
if ( o_next )
{
o_next->prev = 0;
}
lccrt_oper_delete( o);
}
for ( e = lccrt_hash_first( f->lvars); e; e = lccrt_hash_first( f->lvars) )
{
lccrt_var_ptr v = (lccrt_var_ptr)lccrt_hash_get( e);
if ( (v->loc != LCCRT_VAR_LOC_ARG)
&& (v->loc != LCCRT_VAR_LOC_SYSARG) )
{
lccrt_var_delete( v);
}
lccrt_hash_remove( e);
}
lccrt_oper_iterator_set( &(f->cur), 0);
f->start = 0;
return;
} /* lccrt_function_clear */
/**
* Копирование содержимого одной функции в другую.
*/
static lccrt_oper_ptr
lccrt_function_copy_driver_run( lccrt_function_copy_info_t *fci)
{
lccrt_oper_ptr op, new_op;
lccrt_he_ptr e;
lccrt_oper_ptr r = 0;
lccrt_oper_ptr l_after = 0;
lccrt_oper_ptr l_start = 0;
lccrt_var_ptr rvar = 0;
lccrt_var_ptr v = 0;
lccrt_var_ptr w = 0;
lccrt_function_ptr dst = fci->dst_func;
lccrt_function_ptr src = fci->src_func;
lccrt_oper_iterator_ptr oi = lccrt_oper_iterator_new( dst->ctx);
if ( (fci->type == LCCRT_FCT_INLINE) )
{
int i;
int num_args = lccrt_oper_get_num_args( fci->call);
/* Создаем метку для замены возвратов из функции на операции передачи
управления. */
lccrt_oper_iterator_set( oi, fci->call);
l_after = lccrt_oper_new_label( dst, 0, oi);
r = l_after;
/* Создаем переменную для возврата результата из функции. */
if ( lccrt_oper_name_is_res( lccrt_oper_get_name( fci->call)) )
{
rvar = lccrt_var_new_local( dst, lccrt_oper_get_res_type( fci->call), 0);
}
/* Создаем переменные для передачи аргументов в функцию. */
lccrt_oper_iterator_set_prev( oi, fci->call);
for ( i = 1; i < num_args; ++i )
{
new_op = lccrt_oper_new_move( dst, lccrt_oper_get_arg_var( fci->call, i), 0, oi);
w = lccrt_oper_get_res( new_op);
v = lccrt_function_get_arg( src, i - 1);
lccrt_assert( lccrt_var_get_type( v) == lccrt_var_get_type( w));
e = lccrt_hash_push( fci->vars, (uintptr_t)v, 0);
lccrt_hash_set( e, (uintptr_t)w);
}
lccrt_oper_iterator_set_prev( oi, fci->call);
} else
{
lccrt_oper_iterator_set( oi, dst->start);
}
/* Копируем локальные переменные. */
for ( e = lccrt_hash_first( src->lvars); e; e = lccrt_hash_next( e) )
{
lccrt_function_var_import( fci->dst_func, fci->src_func, (lccrt_var_ptr)lccrt_hash_get( e),
fci->vars, fci->types, fci->type == LCCRT_FCT_COPY);
}
/* Копируем исходный код. */
for ( op = src->start; op; op = op->next )
{
/* Сначала копируем только метки. */
if ( (op->name == LCCRT_OPER_LABEL) )
{
lccrt_oper_ptr new_lbl = lccrt_function_oper_import( fci, op, oi);
if ( (op == src->start) )
{
lccrt_assert( !l_start);
l_start = new_lbl;
}
}
}
lccrt_oper_iterator_set( oi, dst->start);
/* Копируем исходный код. */
for ( op = src->start; op; op = op->next )
{
if ( lccrt_oper_is_label( op) )
{
/* Устанавливаем итератор после копии метки. */
e = lccrt_hash_find( fci->opers, (uintptr_t)op);
new_op = e ? (lccrt_oper_ptr)lccrt_hash_get( e) : 0;
lccrt_oper_iterator_set( oi, new_op);
} else if ( (fci->type == LCCRT_FCT_INLINE)
&& (lccrt_oper_is_ret( op)
|| lccrt_oper_is_retval( op)) )
{
if ( lccrt_oper_is_retval( op) )
{
/* Сохраняем результат функции в переменную возврата. */
v = lccrt_oper_get_arg_var( op, 0);
w = lccrt_function_var_import( dst, src, v, fci->vars, fci->types, 0);
new_op = lccrt_oper_new_move( dst, w, rvar, oi);
e = lccrt_hash_push( fci->opers, (uintptr_t)op, 0);
lccrt_hash_set( e, (uintptr_t)new_op);
}
/* Заменяем операцию возврата на операцию перехода. */
new_op = lccrt_oper_new_branch( dst, l_after, oi);
e = lccrt_hash_push( fci->opers, (uintptr_t)op, 0);
lccrt_hash_set( e, (uintptr_t)new_op);
} else
{
/* Копируем операцию. */
lccrt_function_oper_import( fci, op, oi);
}
}
if ( (fci->type == LCCRT_FCT_INLINE) )
{
lccrt_oper_iterator_set_prev( oi, l_start);
lccrt_oper_new_branch( dst, l_start, oi);
if ( lccrt_oper_name_is_res( lccrt_oper_get_name( fci->call)) )
{
lccrt_oper_iterator_set( oi, l_after);
lccrt_oper_new_move( dst, rvar, lccrt_oper_get_res( fci->call), oi);
}
lccrt_oper_delete( fci->call);
fci->call = 0;
}
lccrt_oper_iterator_delete( oi);
return (r);
} /* lccrt_function_copy_driver_run */
/**
* Создание копии функции.
*/
lccrt_function_ptr
lccrt_function_copy( lccrt_m_ptr m, lccrt_f_ptr f, const char *name, const char *asm_name,
lccrt_link_t ln, lccrt_hash_ptr types)
{
lccrt_function_ptr r;
m = m ? m : lccrt_function_get_module( f);
r = lccrt_function_new( m, f->sig_type, name, asm_name, ln,
lccrt_function_is_declaration( f),
lccrt_function_is_builtin( f));
lccrt_function_set_section( r, f->section);
lccrt_function_set_comdat( r, f->comdat);
lccrt_function_set_init_type( r, f->init_type);
lccrt_function_copy_attrs( r, f);
if ( !lccrt_function_is_declaration( r) )
{
lccrt_function_copy_info_t fci;
lccrt_function_copy_info_init( &fci, LCCRT_FCT_COPY, f, r, types, 0);
lccrt_function_copy_driver_run( &fci);
lccrt_function_copy_info_done( &fci);
}
r->opers_num = f->opers_num;
r->lvars_num = f->lvars_num;
r->local_name_id = f->local_name_id;
return (r);
} /* lccrt_function_copy */
/**
* Подстановка вызова функции.
*/
lccrt_oper_ptr
lccrt_function_call_inline( lccrt_o_ptr call, lccrt_f_ptr call_func)
{
lccrt_oper_ptr r;
lccrt_function_copy_info_t fci;
lccrt_function_ptr dst_func = lccrt_oper_get_function( call);
lccrt_function_copy_info_init( &fci, LCCRT_FCT_INLINE, call_func, dst_func, 0, call);
r = lccrt_function_copy_driver_run( &fci);
lccrt_function_copy_info_done( &fci);
return (r);
} /* lccrt_function_call_inline */
/**
* Добавить в функцию новые мета-данные, либо изменить значение старых.
*/
void
lccrt_function_set_einfo( lccrt_function_ptr f, lccrt_einfo_category_t ecat, lccrt_eir_t value)
{
lccrt_module_ptr m = lccrt_function_get_module( f);
lccrt_check_type_assert( f, lccrt_function_t);
lccrt_assert( !lccrt_einfo_is_scalar( value));
f->einfo = lccrt_einfo_link_push_value( m, f->einfo, ecat, value);
return;
} /* lccrt_function_set_einfo */
/**
* Получить значение мета-данных с заданным именем или 0, если таких данных нет.
*/
lccrt_einfo_reference_t
lccrt_function_get_einfo( lccrt_function_ptr f, lccrt_einfo_category_t ecat)
{
lccrt_einfo_link_ptr unit = lccrt_einfo_link_find( f->einfo, ecat);
lccrt_einfo_reference_t r = lccrt_einfo_link_get_value( unit);
lccrt_check_type_assert( f, lccrt_function_t);
return (r);
} /* lccrt_function_get_einfo */