mirror of
https://gitflic.ru/project/e2khome/lccrt.git
synced 2024-11-24 02:40:46 +01:00
294 lines
12 KiB
C
294 lines
12 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_ctx.h - пользовательский интерфейс (динамической) компиляции.
|
||
*/
|
||
|
||
#ifndef LCCRT_CTX_H
|
||
#define LCCRT_CTX_H
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif /* __cplusplus */
|
||
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
#include "lccrt.h"
|
||
#include "internal/lccrt_ilist.h"
|
||
#include "internal/lccrt_hash.h"
|
||
|
||
#define LCCRT_MAX( a, b) (((a) >= (b)) ? (a) : (b))
|
||
#define LCCRT_MIN( a, b) (((a) <= (b)) ? (a) : (b))
|
||
|
||
#ifndef NDEBUG
|
||
/**
|
||
* Макрос задающий тип сборки в отладочном режиме.
|
||
*/
|
||
#define LCCRT_DEBUG
|
||
#endif /* !NDEBUG */
|
||
|
||
/**
|
||
* Преобразование значения в строку.
|
||
*/
|
||
#define LCCRT_TO_STR_OPERATOR( x) #x
|
||
#define LCCRT_TO_STR( x) LCCRT_TO_STR_OPERATOR( x)
|
||
|
||
#define LCCRT_ASM_SFUNC_COMPILE LCCRT_TO_STR( LCCRT_ASM_FUNC_COMPILE)
|
||
#define LCCRT_ASM_SFUNC_GETTOOL LCCRT_TO_STR( LCCRT_ASM_FUNC_GETTOOL)
|
||
|
||
#define LCCRT_PLUGIN_LIBRARY_NAME_S LCCRT_TO_STR( LCCRT_PLUGIN_LIBRARY_NAME)
|
||
#define LCCRT_PLUGIN_LCCRT_VERSION_S LCCRT_TO_STR( LCCRT_PLUGIN_LCCRT_VERSION)
|
||
#define LCCRT_PLUGIN_TARGETS_S LCCRT_TO_STR( LCCRT_PLUGIN_TARGETS)
|
||
|
||
/**
|
||
* Проверка двух строк на равенство.
|
||
*/
|
||
#define lccrt_str_eq( s, p) (strcmp( s, p) == 0)
|
||
#define lccrt_str_eqz( p, q) (!(p) || !(q) || lccrt_str_eq( p, q))
|
||
|
||
#define lccrt_min( a, b) ((a) < (b) ? (a) : (b))
|
||
#define lccrt_max( a, b) ((a) > (b) ? (a) : (b))
|
||
|
||
/**
|
||
* Присвоение под условием.
|
||
*/
|
||
#define lccrt_assign( p, v) ((p) ? ((*(p) = (v)), 0) : 0)
|
||
|
||
/**
|
||
* Исполнить выражение при нулевом значении флаговой переменной с сохранением во
|
||
* флаговую переменную результата выполнения выражения.
|
||
*/
|
||
#define lccrt_test0( flag, expr) ((flag) = ((expr) != 0) || (flag))
|
||
#define lccrt_test1( flag, expr) ((flag) = (!(expr) != 0) || (flag))
|
||
|
||
/**
|
||
* Чтение числа из строки с продвижкой указателя (возвращается 1 при возможности чтения
|
||
* символов из строки s).
|
||
*/
|
||
#define lccrt_strtoll( s, se, base, p) \
|
||
( \
|
||
((s) && (s)[0]) \
|
||
? (((p)[0] = strtoll( s, se, base)), 1) \
|
||
: 0 \
|
||
)
|
||
|
||
/**
|
||
* Интерефейс динамической проверки типов структур.
|
||
*/
|
||
#ifdef LCCRT_DEBUG
|
||
int lccrt_assert_var __attribute__((weak));
|
||
#define lccrt_assert( p) \
|
||
( \
|
||
lccrt_assert_var = ((p) \
|
||
? 0 \
|
||
: (printf( "ERROR: %s: %s:%d\n", __FUNCTION__, __FILE__, __LINE__), \
|
||
abort(), 0)) \
|
||
)
|
||
//#define lccrt_assert( p) assert( p)
|
||
#define lccrt_check_type_name( type) lccrt_check_var__##type
|
||
#define lccrt_check_type_declare( type) extern void *lccrt_check_type_name( type)
|
||
#define lccrt_check_type_define( type) void *lccrt_check_type_name( type)
|
||
#define lccrt_check_type_assert( d, t) \
|
||
( \
|
||
lccrt_assert( !(d) \
|
||
|| (((t *)(d))->type_check.ptr == (void *)&lccrt_check_type_name( t))) \
|
||
)
|
||
#define lccrt_check_type_init( d, t) \
|
||
( \
|
||
((t *)(d))->type_check.ptr = (void *)&lccrt_check_type_name( t) \
|
||
)
|
||
#define lccrt_check_type_done( d, t) \
|
||
( \
|
||
lccrt_check_type_assert( d, t), ((t *)(d))->type_check.ptr = 0 \
|
||
)
|
||
#else /* !LCCRT_DEBUG */
|
||
#define lccrt_assert( p)
|
||
#define lccrt_check_type_assert( d, t)
|
||
#define lccrt_check_type_declare( type)
|
||
#define lccrt_check_type_define( type)
|
||
#define lccrt_check_type_init( d, t)
|
||
#define lccrt_check_type_done( d, t)
|
||
#endif /* LCCRT_DEBUG */
|
||
|
||
/**
|
||
* Структура для динамического контроля типа структур.
|
||
*/
|
||
typedef struct
|
||
{
|
||
#ifdef LCCRT_DEBUG
|
||
void *ptr;
|
||
#endif /* LCCRT_DEBUG */
|
||
} lccrt_check_type_t;
|
||
|
||
/**
|
||
* Типы плагинов.
|
||
*/
|
||
typedef enum
|
||
{
|
||
LCCRT_PLUGIN_TYPE_ASM,
|
||
LCCRT_PLUGIN_TYPE_LAST
|
||
} lccrt_plugin_type_t;
|
||
|
||
/**
|
||
* Типы функций в ассемблере.
|
||
*/
|
||
typedef enum
|
||
{
|
||
LCCRT_PLUGIN_ASM_FUNC_COMP,
|
||
LCCRT_PLUGIN_ASM_FUNC_TOOL,
|
||
LCCRT_PLUGIN_ASM_FUNC_LAST
|
||
} lccrt_plugin_asm_func_name_t;
|
||
|
||
/**
|
||
* Структура внешнего плагина.
|
||
*/
|
||
typedef struct lccrt_plugin_r
|
||
{
|
||
lccrt_context_ptr ctx;
|
||
lccrt_plugin_type_t type; /* тип плагина */
|
||
void *lib; /* плагин */
|
||
const char *lib_name; /* название плагина */
|
||
const char *lccrt_ver; /* версия lccrt-библиотеки, с которой был собран плагин */
|
||
int num_targs; /* количество, поддерживаемых целей */
|
||
const char **targs; /* массив целей */
|
||
int num_funcs; /* количество методов в плагине */
|
||
void **funcs; /* методы плагина */
|
||
const char **lccrt_s; /* пути установки нативных (!) библиотек liblccrt_s */
|
||
const char **include_s; /* пути установки нативных заголовочных файлов */
|
||
lccrt_check_type_t type_check;
|
||
} lccrt_plugin_t;
|
||
|
||
/**
|
||
* Штатные пути для поиска компонент.
|
||
*/
|
||
typedef struct
|
||
{
|
||
char *home; /* корневая директория */
|
||
char *plugin; /* директория поиска плагинов */
|
||
char *plugins[LCCRT_PLUGIN_TYPE_LAST]; /* директория поиска плагинов по типу */
|
||
} lccrt_context_paths_t;
|
||
|
||
/**
|
||
* Данные по типам отладочных печатей.
|
||
*/
|
||
typedef struct
|
||
{
|
||
int8_t is_base; /* информация о переменных окружения, плагинах и т.п. */
|
||
int8_t is_ir; /* создание новых операций */
|
||
} lccrt_context_verbose_t;
|
||
|
||
/**
|
||
* \defgroup tyCtx lccrt_context_t
|
||
* Для работы с библиотекой в начале необходимо создать структуру контекста lccrt_context_t.
|
||
* В основном структура данных lccrt_context_t выполняет технические функции,
|
||
* в частности, можно одновременно создать несколько контекстов. Далее можно работать с разными контекстами
|
||
* независимым образом, причем все последующие данные создаются только в рамках одного из контекстов.
|
||
* При удалении контекста также (автоматически) удаляются все данные, созданные в рамках данного контекста.
|
||
*
|
||
* При создании контекста:
|
||
* - задается \ref lccrt_mem_t "менеджер памяти", с помощью которого должна выделяться память под структуры данных
|
||
* (при использовании внешних библиотек менеджер памяти не пропагируется), причем по умолчанию используются
|
||
* стандартные функции <b><tt> malloc/free </tt></b>
|
||
* - задается \ref lccrt_err_t "менеджер вывода сообщений об ошибках", причем по умолчанию используются
|
||
* стандартные функции <b><tt> printf/abort </tt></b>
|
||
* - происходит загрузка плагинов по штатным путям (см. \ref pgPlg "Загрузка плагинов")
|
||
*
|
||
*/
|
||
/**
|
||
* \class lccrt_context_t
|
||
* \copydoc tyCtx
|
||
*
|
||
* \copydoc tyCtxFns
|
||
*
|
||
* \ref tyCtxFns
|
||
*/
|
||
typedef struct lccrt_context_r
|
||
{
|
||
lccrt_mem_t mem; /*!< интерфейс менеджера памяти */
|
||
lccrt_err_t err; /*!< интерфейс менеджера ошибок */
|
||
lccrt_hash_ptr modules; /* хеш-таблица модулей */
|
||
uint64_t module_max; /* счетчик модулей */
|
||
int num_plgs[LCCRT_PLUGIN_TYPE_LAST]; /* количество штатных плагинов */
|
||
lccrt_plugin_t *plgs[LCCRT_PLUGIN_TYPE_LAST]; /* штатные плагины */
|
||
lccrt_context_paths_t paths; /* пути поиска компонент */
|
||
lccrt_context_verbose_t verbose; /* флаги отладочных печатетей */
|
||
lccrt_check_type_t type_check;
|
||
} lccrt_context_t;
|
||
|
||
/**
|
||
* Стандартный менеджер памяти и поток вывода ошибок.
|
||
*/
|
||
extern lccrt_mem_t lccrt_std_mem;
|
||
extern lccrt_err_t lccrt_std_err;
|
||
|
||
/**
|
||
* Перечисление типов структур с динамической проверкой типа.
|
||
*/
|
||
lccrt_check_type_declare( lccrt_type_t);
|
||
lccrt_check_type_declare( lccrt_varinit_t);
|
||
lccrt_check_type_declare( lccrt_var_t);
|
||
lccrt_check_type_declare( lccrt_oper_t);
|
||
lccrt_check_type_declare( lccrt_oper_iterator_t);
|
||
lccrt_check_type_declare( lccrt_einfo_block_t);
|
||
lccrt_check_type_declare( lccrt_einfo_tydescr_t);
|
||
lccrt_check_type_declare( lccrt_einfo_link_t);
|
||
lccrt_check_type_declare( lccrt_function_t);
|
||
lccrt_check_type_declare( lccrt_function_jit_info_t);
|
||
lccrt_check_type_declare( lccrt_module_t);
|
||
lccrt_check_type_declare( lccrt_context_t);
|
||
lccrt_check_type_declare( lccrt_plugin_t);
|
||
lccrt_check_type_declare( lccrt_fs_t);
|
||
lccrt_check_type_declare( lccrt_jit_t);
|
||
|
||
extern void *lccrt_ctx_malloc_func( lccrt_ctx_ptr ctx, uint64_t size);
|
||
extern void *lccrt_ctx_realloc_func( lccrt_ctx_ptr ctx, void *ptr, uint64_t size);
|
||
extern void *lccrt_ctx_free_func( lccrt_ctx_ptr ctx, void *ptr);
|
||
extern void *lccrt_ctx_memdup_func( lccrt_ctx_ptr ctx, void *ptr, uint64_t len);
|
||
extern void **lccrt_ctx_copy_arr_func( lccrt_ctx_ptr ctx, void **ptr, uint64_t size, uint64_t len);
|
||
extern char *lccrt_ctx_copy_str( lccrt_context_ptr ctx, const char *str);
|
||
extern char *lccrt_ctx_cat_strs( lccrt_context_ptr ctx, const char *str1, const char *str2);
|
||
extern char *lccrt_ctx_catby_strs( lccrt_context_ptr ctx, const char *str1, const char *str2);
|
||
#define lccrt_ctx_malloc( ctx, type) (type *)lccrt_ctx_malloc_func( ctx, sizeof( type))
|
||
#define lccrt_ctx_mallocn( ctx, type, n) ((type *)lccrt_ctx_malloc_func( ctx, (n) * sizeof( type)))
|
||
#define lccrt_ctx_realloc( ctx, ptr, len) lccrt_ctx_realloc_func( ctx, (void *)ptr, len)
|
||
#define lccrt_ctx_free( ctx, ptr) lccrt_ctx_free_func( ctx, (void *)ptr)
|
||
#define lccrt_ctx_memdup( ctx, ptr, len) lccrt_ctx_memdup_func( ctx, (void *)ptr, len)
|
||
#define lccrt_ctx_copy_arr( ctx, ptr, type, n) \
|
||
( \
|
||
(type *)lccrt_ctx_copy_arr_func( ctx, (void **)(ptr), sizeof( type), n) \
|
||
)
|
||
#define lccrt_ctx_error( ctx, eid, fmt, ...) \
|
||
( \
|
||
(ctx)->err.error_func \
|
||
? ((ctx)->err.error_func( (ctx)->err.data, eid, "Error:%s:%d: " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__), 0) \
|
||
: 0 \
|
||
)
|
||
#define lccrt_ctx_warning( ctx, wid, fmt, ...) \
|
||
( \
|
||
(ctx)->err.warning_func \
|
||
? ((ctx)->err.warning_func( (ctx)->err.data, wid, "Warning:%s:%d: " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__), 0) \
|
||
: 0 \
|
||
)
|
||
|
||
extern void *lccrt_ctx_plugin_get_func( lccrt_plg_ptr plg, int func_num);
|
||
|
||
extern lccrt_fs_ptr lccrt_fs_new_file( lccrt_context_ptr ctx, FILE *file);
|
||
extern lccrt_fs_ptr lccrt_fs_open_file( lccrt_context_ptr ctx, const char *name, int is_load);
|
||
extern lccrt_fs_ptr lccrt_fs_new_buffer( lccrt_context_ptr ctx, char *buff, uint64_t buff_size);
|
||
extern int lccrt_fs_delete( lccrt_fs_ptr f);
|
||
extern int lccrt_fs_is_error( lccrt_fs_ptr f);
|
||
extern uint64_t lccrt_fs_get_syms_count( lccrt_fs_ptr f);
|
||
extern char *lccrt_fs_get_buffer( lccrt_fs_ptr f);
|
||
extern int lccrt_fs_get_sym( lccrt_fs_ptr f);
|
||
extern int lccrt_fs_printf( lccrt_fs_ptr f, const char *fmt, ...);
|
||
extern int lccrt_fs_print_name_str( lccrt_fs_ptr f, const char *name);
|
||
|
||
#if defined(__cplusplus)
|
||
}
|
||
#endif
|
||
|
||
#endif /* LCCRT_CTX_H */
|