lccrt/lib/common/lccrt_ctx.c

1146 lines
29 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_ctx.c - реализация пользовательский интерфейс (динамической) компиляции.
*/
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include <dlfcn.h>
#include <libgen.h>
#include <sys/syscall.h>
#include <unistd.h>
#include "lccrt_irv.h"
#define LCCRT_CTX_PLUGIN_MAX_NUMBER (256)
#define LCCRT_CTX_PLUGIN_TARGET_MAX_NUMBER (256)
#define LCCRT_CTX_PLUGIN_NAME_LENGTH (4096 - 1)
#define lccrt_ctx_error_plugin_sym( ctx, lname, sname) \
lccrt_ctx_error( ctx, 0, "Plugin library [%s] hasn't symbol [%s]\n", \
lname, sname)
lccrt_check_type_define( lccrt_type_t);
lccrt_check_type_define( lccrt_varinit_t);
lccrt_check_type_define( lccrt_var_t);
lccrt_check_type_define( lccrt_oper_t);
lccrt_check_type_define( lccrt_oper_iterator_t);
lccrt_check_type_define( lccrt_function_t);
lccrt_check_type_define( lccrt_function_jit_info_t);
lccrt_check_type_define( lccrt_module_t);
lccrt_check_type_define( lccrt_einfo_tydescr_t);
lccrt_check_type_define( lccrt_einfo_block_t);
lccrt_check_type_define( lccrt_einfo_link_t);
lccrt_check_type_define( lccrt_context_t);
lccrt_check_type_define( lccrt_plugin_t);
/**
* Данные стандартного менеджера вывода сообщений в файл.
*/
typedef struct
{
int8_t is_init; /* флаг инициализации структуры */
FILE *file; /* файл для печати сообщений */
pid_t pid; /* идентификатор родительского процесса */
} lccrt_dir_error_info_t;
static void *lccrt_std_alloc( void *pool, uint64_t size);
static void *lccrt_std_realloc( void *pool, void *ptr, uint64_t size);
static void lccrt_std_free( void *pool, void *ptr);
static void lccrt_std_error( void *data, int errid, const char *fmt, ...);
static void lccrt_dir_error( void *data, int errid, const char *fmt, ...);
static void lccrt_std_warning( void *data, int errid, const char *fmt, ...);
static void lccrt_dir_warning( void *data, int errid, const char *fmt, ...);
/**
* Стандартные менеджеры.
*/
lccrt_err_t lccrt_std_err = {0, &lccrt_std_error, &lccrt_std_warning};
lccrt_mem_t lccrt_std_mem = {0, &lccrt_std_alloc, &lccrt_std_realloc, &lccrt_std_free};
lccrt_err_t lccrt_dir_err = {0, &lccrt_dir_error, &lccrt_dir_warning};
/**
* Стандартный malloc.
*/
static void *
lccrt_std_alloc( void *pool, uint64_t size)
{
void *result = (void *)malloc( size);
return (result);
} /* lccrt_std_alloc */
/**
* Стандартный realloc.
*/
static void *
lccrt_std_realloc( void *pool, void *ptr, uint64_t size)
{
void *result = (void *)realloc( ptr, size);
return (result);
} /* lccrt_std_realloc */
/**
* Стандартный free.
*/
static void
lccrt_std_free( void *pool, void *ptr)
{
free( ptr);
return;
} /* lccrt_std_free */
/**
* Стандартная реакция на ошибку.
*/
static void
lccrt_std_error( void *data, int errid, const char *fmt, ...)
{
char str[256];
va_list ap;
va_start( ap, fmt);
vsnprintf( str, 255, fmt, ap);
va_end( ap);
perror( str);
if ( errid )
{
exit( errid);
}
return;
} /* lccrt_std_error */
/**
* Стандартная реакция на предупреждение.
*/
static void
lccrt_std_warning( void *data, int errid, const char *fmt, ...)
{
char str[256];
va_list ap;
va_start( ap, fmt);
vsnprintf( str, 255, fmt, ap);
va_end( ap);
printf( "%s", str);
return;
} /* lccrt_std_warning */
/**
* Подготовка данных для вывода сообщений.
*/
static lccrt_dir_error_info_t *
lccrt_dir_error_init( void)
{
static __thread lccrt_dir_error_info_t ei = {0};
if ( !ei.is_init
|| (ei.pid != getpid()) )
{
char s[1024];
const char *dir_name = getenv( "LCCRT_ERRDIR");
ei.is_init = 1;
ei.pid = getpid();
if ( !dir_name
|| (dir_name[0] == 0) )
{
dir_name = ".";
}
snprintf( s, 1024, "mkdir -p -m a+rwx %s", dir_name);
system( s);
snprintf( s, 1024, "%s/lccrt.errlog.pid_%d.tid_%d.txt", dir_name, getpid(), (unsigned)syscall( SYS_gettid));
ei.file = fopen( s, "w");
}
return (&ei);
} /* lccrt_dir_error_init */
/**
* Стандартная реакция на ошибку.
*/
static void
lccrt_dir_error( void *data, int errid, const char *fmt, ...)
{
va_list ap;
lccrt_dir_error_info_t *ei = lccrt_dir_error_init();
va_start( ap, fmt);
vfprintf( ei->file, fmt, ap);
va_end( ap);
fflush( ei->file);
if ( errid )
{
exit( errid);
}
return;
} /* lccrt_dir_error */
/**
* Стандартная реакция на предупреждение.
*/
static void
lccrt_dir_warning( void *data, int errid, const char *fmt, ...)
{
va_list ap;
lccrt_dir_error_info_t *ei = lccrt_dir_error_init();
va_start( ap, fmt);
vfprintf( ei->file, fmt, ap);
va_end( ap);
fflush( ei->file);
return;
} /* lccrt_dir_warning */
/**
* Чтение из файла строки.
*/
static void
lccrt_getline( FILE *f, int max_str_len, char *line)
{
int c;
int k = 0;
c = getc( f);
while ( (c != '\n')
&& (c != EOF)
&& isspace( c) )
{
c = getc( f);
}
while ( (c != '\n')
&& (c != EOF) )
{
if ( (k < max_str_len) )
{
line[k] = c;
++k;
}
c = getc( f);
}
line[k] = 0;
return;
} /* lccrt_getline */
/**
* Получить ссылку на метод.
*/
void *
lccrt_ctx_plugin_get_func( lccrt_plg_ptr p, int func_num)
{
void *r = 0;
lccrt_check_type_assert( p, lccrt_plugin_t);
if ( (0 <= func_num)
&& (func_num < p->num_funcs) )
{
r = p->funcs[func_num];
}
return (r);
} /* lccrt_ctx_plugin_get_func */
/**
* Закрытие библиотеки с ассемблером.
*/
static void
lccrt_ctx_plugin_unload( lccrt_plugin_t *a)
{
int k;
lccrt_context_ptr ctx = a->ctx;
lccrt_check_type_assert( a, lccrt_plugin_t);
if ( a->lib )
{
dlclose( a->lib);
a->lib = 0;
}
if ( a->targs )
{
for ( k = 0; k < a->num_targs; ++k )
{
lccrt_ctx_free( ctx, a->targs[k]);
lccrt_ctx_free( ctx, a->lccrt_s[k]);
lccrt_ctx_free( ctx, a->include_s[k]);
}
lccrt_ctx_free( ctx, a->targs);
lccrt_ctx_free( ctx, a->lccrt_s);
lccrt_ctx_free( ctx, a->include_s);
a->targs = 0;
}
lccrt_ctx_free( ctx, a->lib_name);
lccrt_ctx_free( ctx, a->lccrt_ver);
lccrt_ctx_free( ctx, a->lccrt_s);
lccrt_ctx_free( ctx, a->include_s);
a->lib_name = 0;
a->lccrt_ver = 0;
a->lccrt_s = 0;
a->include_s = 0;
a->num_targs = 0;
a->num_funcs = 0;
lccrt_ctx_free( ctx, a->funcs);
a->funcs = 0;
return;
} /* lccrt_ctx_plugin_unload */
/**
* Открытие библиотеки с ассемблером.
*/
static int
lccrt_ctx_load_plugin_lib( lccrt_plugin_t *a, const char *lib_name)
{
int k;
int r = -1;
char *cur_name = 0;
lccrt_context_ptr ctx = a->ctx;
lccrt_check_type_assert( a, lccrt_plugin_t);
if ( a->lib )
{
lccrt_ctx_error( ctx, 0, "INTERNAL ERROR\n");
return (r);
}
if ( (lib_name[0] == '/') )
{
cur_name = lccrt_ctx_copy_str( ctx, lib_name);
} else
{
cur_name = lccrt_ctx_cat_strs( ctx, ctx->paths.plugins[a->type], "/");
cur_name = lccrt_ctx_catby_strs( ctx, cur_name, lib_name);
}
a->lib = dlopen( cur_name, RTLD_LAZY);
if ( !a->lib )
{
lccrt_ctx_error( ctx, 0, "Can't load plugin library [%s]\n", cur_name);
} else
{
const char **lname;
const char **lver;
const char *(*targs)[];
int is_asm = (a->type == LCCRT_PLUGIN_TYPE_ASM);
a->num_funcs = LCCRT_PLUGIN_ASM_FUNC_LAST;
a->funcs = lccrt_ctx_mallocn( ctx, void *, a->num_funcs);
if ( is_asm )
{
a->funcs[LCCRT_PLUGIN_ASM_FUNC_COMP] = dlsym( a->lib, LCCRT_ASM_SFUNC_COMPILE);
a->funcs[LCCRT_PLUGIN_ASM_FUNC_TOOL] = dlsym( a->lib, LCCRT_ASM_SFUNC_GETTOOL);
if ( !a->funcs[LCCRT_PLUGIN_ASM_FUNC_COMP] )
{
lccrt_ctx_error_plugin_sym( ctx, cur_name, LCCRT_ASM_SFUNC_COMPILE);
} else if ( !a->funcs[LCCRT_PLUGIN_ASM_FUNC_TOOL] )
{
lccrt_ctx_error_plugin_sym( ctx, cur_name, LCCRT_ASM_SFUNC_GETTOOL);
}
} else
{
lccrt_assert( 0);
}
lname = dlsym( a->lib, LCCRT_PLUGIN_LIBRARY_NAME_S);
lver = dlsym( a->lib, LCCRT_PLUGIN_LCCRT_VERSION_S);
targs = dlsym( a->lib, LCCRT_PLUGIN_TARGETS_S);
if ( !lname
|| !lname[0] )
{
lccrt_ctx_error_plugin_sym( ctx, cur_name, LCCRT_PLUGIN_LIBRARY_NAME_S);
} else if ( !lname[0][0] )
{
lccrt_ctx_error( ctx, 0, "Plugin library [%s] name [%s] is incorrect\n",
cur_name, lname[0]);
} else if ( !lver
|| !lver[0] )
{
lccrt_ctx_error_plugin_sym( ctx, cur_name, LCCRT_PLUGIN_LCCRT_VERSION_S);
} else if ( !targs )
{
lccrt_ctx_error_plugin_sym( ctx, cur_name, LCCRT_PLUGIN_TARGETS_S);
} else
{
if ( ctx->verbose.is_base )
{
fprintf( stderr, "LCCRT: plugin [%s] config:\n", lib_name);
}
a->lib_name = lccrt_ctx_copy_str( ctx, lname[0]);
a->lccrt_ver = lccrt_ctx_copy_str( ctx, lver[0]);
if ( ctx->verbose.is_base )
{
fprintf( stderr, " plugin self-name : %s\n", a->lib_name);
fprintf( stderr, " plugin's version of lccrt-library : %s\n", a->lccrt_ver);
}
a->num_targs = 0;
for ( k = 0; (*targs)[k]; ++k )
{
a->num_targs++;
}
if ( (0 < a->num_targs)
&& (a->num_targs < LCCRT_CTX_PLUGIN_TARGET_MAX_NUMBER) )
{
r = 0;
a->targs = lccrt_ctx_mallocn( ctx, const char *, a->num_targs);
a->lccrt_s = lccrt_ctx_mallocn( ctx, const char *, a->num_targs);
a->include_s = lccrt_ctx_mallocn( ctx, const char *, a->num_targs);
memset( a->targs, 0, a->num_targs*sizeof( a->lccrt_s[0]));
memset( a->lccrt_s, 0, a->num_targs*sizeof( a->lccrt_s[0]));
memset( a->include_s, 0, a->num_targs*sizeof( a->include_s[0]));
for ( k = 0; k < a->num_targs; ++k )
{
char buf[1024] = {0};
a->targs[k] = lccrt_ctx_copy_str( ctx, (*targs)[k]);
if ( ctx->verbose.is_base )
{
fprintf( stderr, " plugin's target (%d) : %s\n", k, a->targs[k]);
}
snprintf( buf, 1024, "%s/lib/%s", ctx->paths.home, a->targs[k]);
a->lccrt_s[k] = lccrt_ctx_copy_str( ctx, buf);
if ( ctx->verbose.is_base )
{
fprintf( stderr, " plugin's target system libraries path : %s\n", a->lccrt_s[k]);
}
snprintf( buf, 1024, "%s/include/%s", ctx->paths.home, a->targs[k]);
a->include_s[k] = lccrt_ctx_copy_str( ctx, buf);
if ( ctx->verbose.is_base )
{
fprintf( stderr, " plugin's target system include path : %s\n", a->include_s[k]);
}
if ( lccrt_str_eq( a->lib_name, "lccopt-e2k64") )
{
FILE *flib = 0;
snprintf( buf, 1024, "%s/liblccrt_s.a", a->lccrt_s[k]);
flib = fopen( buf, "r");
if ( !flib )
{
r = -1;
lccrt_ctx_error( ctx, 0, "Can't find system library [liblccrt_s.a] by path [%s]\n",
a->lccrt_s[k]);
break;
} else
{
fclose( flib);
}
}
}
} else
{
a->num_targs = 0;
lccrt_ctx_error( ctx, 0, "Plugin library [%s] number of targets [%d]\n",
cur_name, a->num_targs);
}
}
}
lccrt_ctx_free( ctx, cur_name);
if ( r )
{
lccrt_ctx_plugin_unload( a);
}
return (r);
} /* lccrt_ctx_load_plugin_lib */
/**
* Поиск lccrt-home пути на основе пути к liblccrt.so (места расположения загруженной библиотеки).
*/
char *
lccrt_ctx_find_home_path( lccrt_ctx_ptr ctx)
{
Dl_info dli;
char *t = 0;
char *s = 0;
dladdr( &lccrt_ctx_find_home_path, &dli);
t = realpath( dli.dli_fname, 0);
if ( !t )
{
lccrt_ctx_error( ctx, 0, "Can't resolve real path of lccrt-library's location [%s]\n", dli.dli_fname);
}
s = dirname( t);
if ( !s )
{
lccrt_ctx_error( ctx, 0, "Can't resolve directory of lccrt-library's location [%s]\n", t);
}
s = lccrt_ctx_cat_strs( ctx, s, "/lccrt");
free( t);
return (s);
} /* lccrt_ctx_find_home_path */
/**
* Загрузка плагина.
*/
static int
lccrt_ctx_load_plugin( lccrt_ctx_ptr ctx, lccrt_plugin_type_t type, const char *env, const char *dir)
{
int k;
int r = 0;
char *f_name = 0;
FILE *f = 0;
int num_ps = 0;
lccrt_plugin_t ps[LCCRT_CTX_PLUGIN_MAX_NUMBER] = {0};
if ( getenv( env) )
{
ctx->paths.plugins[type] = lccrt_ctx_copy_str( ctx, getenv( env));
} else
{
ctx->paths.plugins[type] = lccrt_ctx_cat_strs( ctx, ctx->paths.plugin, "/");
ctx->paths.plugins[type] = lccrt_ctx_cat_strs( ctx, ctx->paths.plugins[type], dir);
}
f_name = lccrt_ctx_cat_strs( ctx, ctx->paths.plugins[type], "/plugin.conf");
f = fopen( f_name, "r");
if ( !f )
{
lccrt_ctx_error( ctx, 0, "Can't open plugin [%s] config file [%s]\n", dir, f_name);
lccrt_ctx_free( ctx, f_name);
r = -1;
} else
{
char name[LCCRT_CTX_PLUGIN_NAME_LENGTH + 1];
lccrt_ctx_free( ctx, f_name);
while ( !feof( f) )
{
lccrt_getline( f, LCCRT_CTX_PLUGIN_NAME_LENGTH, name);
if ( (name[0] == '#')
|| (name[0] == 0) )
{
/* Пропускаем текущую строчку. */
} else
{
if ( (num_ps < LCCRT_CTX_PLUGIN_MAX_NUMBER) )
{
int is_load = 0;
lccrt_check_type_init( ps + num_ps, lccrt_plugin_t);
ps[num_ps].ctx = ctx;
ps[num_ps].type = type;
if ( (lccrt_ctx_load_plugin_lib( ps + num_ps, name) == 0) )
{
is_load = 1;
num_ps++;
for ( k = 0; k < num_ps - 1; ++k )
{
if ( lccrt_str_eq( ps[k].lib_name, ps[num_ps-1].lib_name) )
{
is_load = 0;
lccrt_ctx_error( ctx, 0, "Duplicate plugin name [%s]\n",
ps[k].lib_name);
break;
}
}
}
if ( !is_load )
{
lccrt_ctx_error( ctx, 0, "Can't load plugin [%s]\n", name);
for ( k = 0; k < num_ps; ++k )
{
lccrt_ctx_plugin_unload( ps + k);
}
lccrt_context_delete( ctx);
return (0);
}
}
}
}
fclose( f);
if ( (num_ps == 0) )
{
//lccrt_ctx_warning( ctx, 0, "The plugin [%s] set is empty\n", dir);
} else
{
ctx->num_plgs[type] = num_ps;
ctx->plgs[type] = lccrt_ctx_memdup( ctx, ps, num_ps * sizeof( ps[0]));
}
}
return (r);
} /* lccrt_ctx_load_plugin */
/**
* Создание контекста (конструктор).
* ---------------------------------
* @param mem менеджер памяти (0 - менеджер по умолчанию)
* @param err менеджер сообщений об ошибках (0 - менеджер по умолчанию)
* @result новый контекст, созданный с помощью менеджера памяти
*
* @ingroup tyCtxFns
*/
lccrt_context_ptr
lccrt_context_new( lccrt_mem_ptr mem, lccrt_err_ptr err)
{
int k;
lccrt_context_ptr ctx = 0;
FILE *pc = 0;
if ( !mem )
{
mem = &lccrt_std_mem;
}
if ( !err )
{
err = &lccrt_std_err;
}
if ( getenv( "LCCRT_ERRDIR") )
{
err = &lccrt_dir_err;
}
ctx = (*mem->palloc)( mem->pool, sizeof( lccrt_context_t));
memset( ctx, 0, sizeof( lccrt_context_t));
lccrt_check_type_init( ctx, lccrt_context_t);
ctx->mem = *mem;
ctx->err = *err;
ctx->modules = lccrt_hash_new( ctx, LCCRT_HASH_KEY_INTPTR);
ctx->module_max = 0;
if ( getenv( "LCCRT_HOME") )
{
ctx->paths.home = lccrt_ctx_copy_str( ctx, getenv( "LCCRT_HOME"));
} else
{
ctx->paths.home = lccrt_ctx_find_home_path( ctx);
}
if ( getenv( "LCCRT_HOME_PLUGIN") )
{
ctx->paths.plugin = lccrt_ctx_copy_str( ctx, getenv( "LCCRT_HOME_PLUGIN"));
} else
{
ctx->paths.plugin = lccrt_ctx_cat_strs( ctx, ctx->paths.home, "/plugin");
}
if ( getenv( "LCCRT_VERBOSE") )
{
ctx->verbose.is_base = atoi( getenv( "LCCRT_VERBOSE"));
}
lccrt_ctx_load_plugin( ctx, LCCRT_PLUGIN_TYPE_ASM, "LCCRT_PLUGIN_TYPE_ASM", "asm");
return (ctx);
} /* lccrt_context_new */
/**
* Удаление контекста (деструктор).
* --------------------------------
* @param ctx удаляемый контекст
*
* @ingroup tyCtxFns
*/
void
lccrt_context_delete( lccrt_context_ptr ctx)
{
lccrt_hash_entry_ptr he;
lccrt_check_type_assert( ctx, lccrt_context_t);
/* Удаляем все ранее созданные модули. */
while ( (he = lccrt_hash_first( ctx->modules)) )
{
lccrt_module_delete( (lccrt_module_ptr)lccrt_hash_get_key( he));
}
lccrt_hash_delete( ctx->modules);
lccrt_ctx_free( ctx, ctx->paths.home);
lccrt_ctx_free( ctx, ctx->paths.plugin);
lccrt_ctx_free( ctx, ctx->paths.plugins[LCCRT_PLUGIN_TYPE_ASM]);
lccrt_check_type_done( ctx, lccrt_context_t);
(*ctx->mem.pfree)( ctx->mem.pool, ctx);
return;
} /* lccrt_context_delete */
/**
* Прочитать свойство.
*/
int
lccrt_context_get_verbose_ir( lccrt_context_ptr ctx)
{
int r = ctx->verbose.is_ir;
lccrt_check_type_assert( ctx, lccrt_context_t);
return (r);
} /* lccrt_context_get_verbose_ir */
/**
* Установить свойство.
*/
void
lccrt_context_set_verbose_ir( lccrt_context_ptr ctx, int value)
{
lccrt_check_type_assert( ctx, lccrt_context_t);
ctx->verbose.is_ir = value;
return;
} /* lccrt_context_set_verbose_ir */
/**
* Поиск плагина.
*/
static lccrt_plugin_t *
lccrt_context_find_plugin( lccrt_context_ptr c, lccrt_plugin_type_t type, const char *plg_name, int is_assert)
{
int k;
lccrt_plugin_t *r = 0;
if ( plg_name )
{
for ( k = 0; k < c->num_plgs[type]; ++k )
{
if ( lccrt_str_eq( plg_name, c->plgs[type][k].lib_name) )
{
r = c->plgs[type] + k;
break;
}
}
}
if ( !r
&& is_assert )
{
lccrt_ctx_error( c, 0, "No plugin with name [%s]\n", plg_name);
}
return (r);
} /* lccrt_context_find_plugin */
/**
* Поиск плагина.
*/
static lccrt_plg_ptr
lccrt_context_find_plugin_for_arch( lccrt_context_ptr c, lccrt_plugin_type_t type, const char *arch)
{
int k, i;
lccrt_plg_ptr r = 0;
for ( k = 0; k < c->num_plgs[type] && !r; ++k )
{
lccrt_plg_ptr p = c->plgs[type] + k;
for ( i = 0; i < p->num_targs; ++i )
{
if ( lccrt_str_eq( arch, p->targs[i]) )
{
r = p;
break;
}
}
}
if ( !r )
{
lccrt_ctx_error( c, 0, "No plugin for target [%s]\n", arch);
}
return (r);
} /* lccrt_context_find_plugin_for_arch */
/**
* Получить ссылку на плагин.
*/
lccrt_plg_ptr
lccrt_context_get_plugin_asm( lccrt_ctx_ptr ctx, const char *plg_name)
{
lccrt_plg_ptr r = lccrt_context_find_plugin( ctx, LCCRT_PLUGIN_TYPE_ASM, plg_name, 1);
return (r);
} /* lccrt_context_get_plugin_asm */
/**
* Поиск ассемблера.
*/
static int
lccrt_context_find_target( lccrt_context_ptr c, lccrt_plugin_t *a, const char *targ, int is_assert)
{
int k;
int r = -1;
if ( a )
{
if ( targ )
{
for ( k = 0; k < a->num_targs; ++k )
{
if ( lccrt_str_eq( targ, a->targs[k]) )
{
r = k;
break;
}
}
}
if ( (r < 0)
&& is_assert )
{
lccrt_ctx_error( c, 0, "In plugin [%s] no target [%s]\n", a->lib_name, targ);
}
}
return (r);
} /* lccrt_context_find_target */
/**
* Компиляция модуля.
*/
int
lccrt_module_compile_asm( lccrt_module_ptr m, const char *asm_lib,
lccrt_asm_compile_config_t *cnf)
{
int k;
int r = -1;
lccrt_context_ptr c = lccrt_module_get_context( m);
lccrt_plugin_t *a = lccrt_context_get_plugin_asm( c, asm_lib);
if ( cnf->is_jit )
{
assert( 0);
}
if ( 0 )
{
lccrt_fs_ptr fs = lccrt_fs_new_file( c, stdout);
lccrt_asm_print_module( fs, m);
lccrt_fs_delete( fs);
}
if ( (lccrt_context_find_target( c, a, cnf->target, 1) >= 0) )
{
r = ((lccrt_asm_compile_t)a->funcs[LCCRT_PLUGIN_ASM_FUNC_COMP])( m, cnf);
}
return (r);
} /* lccrt_module_compile_asm */
/**
* Получить значение утилиты.
*/
const char *
lccrt_context_get_toolchain( lccrt_ctx_ptr c, const char *asm_lib, const char *targ,
const char *tool_type, const char *tool_name)
{
const char *r = "";
lccrt_plugin_t *a = lccrt_context_get_plugin_asm( c, asm_lib);
int k = lccrt_context_find_target( c, a, targ, 1);
if ( (k >= 0) )
{
if ( lccrt_str_eq( tool_type, "lib_path")
&& lccrt_str_eq( tool_name, "lccrt_s") )
{
r = a->lccrt_s[k];
} else if ( lccrt_str_eq( tool_type, "include_path")
&& lccrt_str_eq( tool_name, "system") )
{
r = a->include_s[k];
} else
{
r = ((lccrt_asm_gettool_t)a->funcs[LCCRT_PLUGIN_ASM_FUNC_TOOL])( targ, tool_type, tool_name);
}
}
return (r);
} /* lccrt_context_get_toolchain */
/**
* Получить значение поля.
*/
lccrt_err_t
lccrt_context_get_err_info( lccrt_ctx_ptr ctx)
{
lccrt_err_t r;
lccrt_check_type_assert( ctx, lccrt_context_t);
r = ctx->err;
return (r);
} /* lccrt_context_get_err_info */
/**
* Установить значение поля.
*/
lccrt_err_t
lccrt_context_set_err_info( lccrt_ctx_ptr ctx, lccrt_err_t err)
{
lccrt_err_t r;
lccrt_check_type_assert( ctx, lccrt_context_t);
r = ctx->err;
ctx->err = err;
return (r);
} /* lccrt_context_set_err_info */
/**
* Выделение участка памяти.
*/
void *
lccrt_ctx_malloc_func( lccrt_ctx_ptr ctx, uint64_t size)
{
void *r;
lccrt_check_type_assert( ctx, lccrt_context_t);
r = ctx->mem.palloc( &(ctx->mem), size);
return (r);
} /* lccrt_ctx_malloc_func */
/**
* Выделение участка памяти.
*/
void *
lccrt_ctx_realloc_func( lccrt_ctx_ptr ctx, void *ptr, uint64_t size)
{
void *r;
lccrt_check_type_assert( ctx, lccrt_context_t);
r = ctx->mem.prealloc( &(ctx->mem), ptr, size);
return (r);
} /* lccrt_ctx_realloc_func */
/**
* Освобождение участка памяти.
*/
void *
lccrt_ctx_free_func( lccrt_ctx_ptr ctx, void *ptr)
{
lccrt_check_type_assert( ctx, lccrt_context_t);
if ( ptr )
{
ctx->mem.pfree( &(ctx->mem), ptr);
}
return (0);
} /* lccrt_ctx_free_func */
/**
* Копирование участка памяти.
*/
void *
lccrt_ctx_memdup_func( lccrt_ctx_ptr ctx, void *ptr, uint64_t size)
{
void *r = 0;
lccrt_check_type_assert( ctx, lccrt_context_t);
if ( (size > 0) )
{
r = ctx->mem.palloc( &(ctx->mem), size);
if ( ptr )
{
memcpy( r, ptr, size);
} else
{
memset( r, 0, size);
}
}
return (r);
} /* lccrt_ctx_memdup_func */
/**
* Копирование массива.
*/
void **
lccrt_ctx_copy_arr_func( lccrt_ctx_ptr ctx, void **ptr, uint64_t size, uint64_t len)
{
uint64_t k;
void **r = 0;
if ( (len > 0) )
{
r = lccrt_ctx_malloc_func( ctx, len * sizeof( r[0]));
for ( k = 0; k < len; ++k )
{
r[k] = lccrt_ctx_memdup_func( ctx, ptr[k], size);
}
}
return (r);
} /* lccrt_ctx_copy_arr_func */
/**
* Копирование участка памяти.
*/
char *
lccrt_ctx_copy_str( lccrt_ctx_ptr ctx, const char *str)
{
void *r = 0;
if ( str )
{
r = (char *)lccrt_ctx_memdup_func( ctx, (void *)str, strlen( str) + 1);
}
return (r);
} /* lccrt_ctx_copy_str */
/**
* Объединение строк.
*/
char *
lccrt_ctx_cat_strs( lccrt_ctx_ptr ctx, const char *str1, const char *str2)
{
char *r = 0;
int len1 = str1 ? strlen( str1) : 0;
int len2 = str2 ? strlen( str2) : 0;
r = lccrt_ctx_malloc_func( ctx, len1 + len2 + 1);
memcpy( r, str1, len1);
memcpy( r + len1, str2, len2);
r[len1 + len2] = 0;
return (r);
} /* lccrt_ctx_cat_strs */
/**
* Объединение строк.
*/
char *
lccrt_ctx_catby_strs( lccrt_ctx_ptr ctx, const char *str1, const char *str2)
{
char *r = lccrt_ctx_cat_strs( ctx, str1, str2);
lccrt_ctx_free( ctx, str1);
return (r);
} /* lccrt_ctx_catby_strs */
/**
* Старт внешней программы с перенаправлением стандартного потока вывода
* на канальные файловые дескрипторы.
*/
int
lccrt_exec_with_fork( const char *path, /* первый аргумент execv */
char *argv[], /* второй аргумент execv */
pid_t *wpid,
int fds[2]) /* fds[0] - выходной декскриптор для внешней программы,
fds[1] - входной декскриптор для внешней программы */
{
pid_t pid;
int ifd[2] = {-1, -1};
int ofd[2] = {-1, -1};
int r = -1;
if ( wpid )
{
wpid[0] = -1;
}
if ( fds )
{
if ( (pipe( ifd) != 0) )
{
/* Не удалось создать канал. */
return (r);
}
if ( (pipe( ofd) != 0) )
{
/* Не удалось создать канал. */
return (r);
}
}
pid = fork();
if ( (pid < 0) )
{
/* Не удалось создать процесс. */
return (r);
}
if ( (pid == 0) )
{
/* Запускаем внешнюю программу. */
if ( fds )
{
close( ifd[1]);
dup2( ifd[0], STDIN_FILENO);
close( ifd[0]);
close( ofd[0]);
dup2( ofd[1], STDOUT_FILENO);
dup2( ofd[1], STDERR_FILENO);
close( ofd[1]);
}
execvp( path, argv);
} else
{
/* Возвращаем файловые дескрипторы с вводом и выводом внешней программы. */
r = 0;
if ( fds )
{
close( ifd[0]);
close( ofd[1]);
fds[0] = ofd[0];
fds[1] = ifd[1];
}
if ( wpid )
{
(*wpid) = pid;
}
}
return (r);
} /* lccrt_exec_with_fork */