lccrt/lib/irv/lccrt_irwriter.c

1487 lines
46 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_irwriter.c - реализация печати представления модуля.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "lccrt_real.h"
/**
* Данные для печати представления модуля.
*/
typedef struct
{
lccrt_context_ptr ctx;
lccrt_module_ptr m;
int fd;
uintptr_t tident; // идентификатор типов
uintptr_t nident; // идентификатор сокращенных имен
lccrt_hash_ptr ptypes; // хеш-таблица с напечатанными типами (тип,номер)
lccrt_hash_ptr snames; // хеш-таблица с сокращенными именами для глобалов и функций
lccrt_hash_ptr typelinks; // хеш-таблица с именованными типами, для которых выполнено связывание
lccrt_hash_ptr einfos; // хеш-таблица с идентификаторами метаданных
lccrt_hash_ptr eitydes; // хеш-таблица с идентификаторами типов метаданных
} lccrt_irwriter_t;
/**
* Форматный вывод.
*/
static int
lccrt_printf( lccrt_irwriter_t *irw, const char *fmt, ...)
{
int n1, n2;
va_list args;
int r = -1;
char *b = 0;
lccrt_ctx_ptr ctx = irw->ctx;
int fd = irw->fd;
va_start( args, fmt);
n1 = vsnprintf( 0, 0, fmt, args);
va_end( args);
b = lccrt_ctx_mallocn( ctx, char, n1 + 4);
va_start( args, fmt);
n2 = vsnprintf( b, n1 + 2, fmt, args);
va_end( args);
if ( (n1 > 0)
&& (b != 0)
&& (n2 == n1) )
{
int k = 0;
while ( (k >= 0)
&& (k < n2) )
{
int l = write( fd, b + k, n2 - k);
k = (l > 0) ? (k + l) : -1;
}
if ( (k == n2) )
{
r = n2;
}
}
lccrt_ctx_free( ctx, b);
lccrt_assert( r >= 0);
return (r);
} /* lccrt_printf */
/**
* Получение стандартной строки для значения.
*/
static const char *
lccrt_get_loc_str( lccrt_var_loc_t loc)
{
const char *r = "UNKNOWN";
switch ( loc )
{
case LCCRT_VAR_LOC_GLOB: r = "glob"; break;
case LCCRT_VAR_LOC_EXT: r = "ext"; break;
case LCCRT_VAR_LOC_CONSTARG: r = "carg"; break;
case LCCRT_VAR_LOC_LOCAL: r = "local"; break;
case LCCRT_VAR_LOC_ARG: r = "arg"; break;
case LCCRT_VAR_LOC_SYSARG: r = "sarg"; break;
case LCCRT_VAR_LOC_ASM: r = "arg"; break;
default: lccrt_assert( 0); break;
}
return (r);
} /* lccrt_get_loc_str */
/**
* Получение стандартной строки для значения.
*/
static const char *
lccrt_get_bnd_str( lccrt_link_bind_t bnd)
{
const char *r = "UNKNOWN";
switch ( bnd )
{
case LCCRT_LINK_BND_NO: r = "no"; break;
case LCCRT_LINK_BND_WEAK: r = "weak"; break;
case LCCRT_LINK_BND_GLOBAL: r = "glob"; break;
case LCCRT_LINK_BND_LOCAL: r = "loc"; break;
default: lccrt_assert( 0); break;
}
return (r);
} /* lccrt_get_bnd_str */
/**
* Получение стандартной строки для значения.
*/
static const char *
lccrt_get_vis_str( lccrt_link_visibility_t vis)
{
const char *r = "UNKNOWN";
switch ( vis )
{
case LCCRT_LINK_VIS_DEFAULT: r = "def"; break;
case LCCRT_LINK_VIS_INTERNAL: r = "int"; break;
case LCCRT_LINK_VIS_HIDDEN: r = "hid"; break;
case LCCRT_LINK_VIS_PROTECTED: r = "pro"; break;
default: lccrt_assert( 0); break;
}
return (r);
} /* lccrt_get_vis_str */
/**
* Получение стандартной строки для значения.
*/
static const char *
lccrt_get_tls_str( lccrt_link_tls_t tls)
{
const char *r = "UNKNOWN";
switch ( tls )
{
case LCCRT_LINK_TLS_NO: r = "no"; break;
case LCCRT_LINK_TLS_DYNAMIC_G: r = "dyn_g"; break;
case LCCRT_LINK_TLS_DYNAMIC_L: r = "dyn_l"; break;
case LCCRT_LINK_TLS_EXEC_I: r = "exec_i"; break;
case LCCRT_LINK_TLS_EXEC_L: r = "exec_l"; break;
default: lccrt_assert( 0); break;
}
return (r);
} /* lccrt_get_tls_str */
/**
* Удаление таблицы вместе с данными.
*/
static lccrt_hash_ptr
lccrt_delete_hash_with_data( lccrt_ctx_ptr ctx, lccrt_hash_ptr tbl)
{
lccrt_he_ptr e;
for ( e = lccrt_hash_first( tbl); e; e = lccrt_hash_next( e) )
{
lccrt_ctx_free( ctx, (char *)lccrt_hash_get( e));
}
lccrt_hash_delete( tbl);
return (0);
} /* lccrt_delete_hash_with_data */
/**
* Печать массива симолов с помещением в двойные кавычки, а также экранирования всех
* не печатных символов.
*/
static int64_t
lccrt_print_escaped_bytearray( lccrt_irwriter_t *irw, int64_t len, const char *s)
{
int64_t i;
int64_t r = 0;
r += lccrt_printf( irw, "\"");
for ( i = 0; i < len; ++i )
{
if ( isprint( s[i])
&& (s[i] != '"')
&& (s[i] != '\\') )
{
r += lccrt_printf( irw, "%c", s[i]);
} else
{
r += lccrt_printf( irw, "\\%02x", (uint8_t)s[i]);
}
}
r += lccrt_printf( irw, "\"");
return (r);
} /* lccrt_print_escaped_bytearray */
/**
* Печать строки с помещением в двойные кавычки, а также экранирования всех
* не печатных символов.
*/
static int64_t
lccrt_print_escaped_string( lccrt_irwriter_t *irw, const char *s)
{
int64_t r = lccrt_print_escaped_bytearray( irw, strlen( s), s);
return (r);
} /* lccrt_print_escaped_string */
/**
* Напечатать определение, инициализируемое строкой с экранированием.
*/
static void
lccrt_print_define_string( lccrt_irwriter_t *irw, const char *var, const char *str)
{
str = str ? str : "";
lccrt_printf( irw, var);
lccrt_print_escaped_string( irw, str);
lccrt_printf( irw, ";\n");
return;
} /* lccrt_print_define_string */
/**
* Напечатать определение, инициализируемое строкой с экранированием.
*/
static void
lccrt_print_attr_string( lccrt_irwriter_t *irw, const char *attr, const char *str)
{
lccrt_printf( irw, " %s(", attr);
lccrt_print_escaped_string( irw, str);
lccrt_printf( irw, ")");
return;
} /* lccrt_print_attr_string */
/**
* Проверяем, что строка является стандартным идентификатором.
*/
static int
lccrt_is_str_ident( const char *s)
{
int i;
int r = 0;
if ( (s[0] == '_')
|| isalpha( s[0]) )
{
r = 1;
for ( i = 1; s[i]; ++i )
{
if ( !((s[i] == '_')
|| isalnum( s[i])) )
{
r = 0;
break;
}
}
}
return (r);
} /* lccrt_is_str_ident */
/**
* Печать идентификатора с экранированием кавычками по необходимости.
*/
static int
lccrt_print_ident( lccrt_irwriter_t *irw, const char *s)
{
int r = 0;
if ( lccrt_is_str_ident( s)
&& (strcmp( s, "loc") != 0) )
{
r = lccrt_printf( irw, "%s", s);
} else
{
r = lccrt_print_escaped_string( irw, s);
}
return (r);
} /* lccrt_print_ident */
/**
* Для ранее определенного типа получить его строковый идентификатор.
*/
static char *
lccrt_irwriter_get_type_ident( lccrt_irwriter_t *irw, lccrt_type_ptr t)
{
lccrt_he_ptr e = lccrt_hash_find( irw->ptypes, (uintptr_t)t);
char *r = (char *)lccrt_hash_get( e);
return (r);
} /* lccrt_irwriter_get_type_ident */
/**
* Для ранее определенного имени получить его сокращенное название.
*/
static char *
lccrt_irwriter_get_name_ident( lccrt_irwriter_t *irw, void *obj)
{
lccrt_he_ptr e = lccrt_hash_find( irw->snames, (uintptr_t)obj);
char *r = (char *)lccrt_hash_get( e);
return (r);
} /* lccrt_irwriter_get_name_ident */
/**
* Печать определения типа.
*/
static void
lccrt_irwriter_define_type( lccrt_irwriter_t *irw, lccrt_type_ptr t_src, lccrt_type_ptr t,
int is_pointer, char **tnameout)
{
int fd = irw->fd;
int is_new = 0;
lccrt_he_ptr e = lccrt_hash_push( irw->ptypes, (uintptr_t)t, &is_new);
if ( is_new )
{
char tname[256];
int tlen = -1;
int is_simple = 1;
char *tname0 = "UNKNOWN";
uint64_t tnum_args = lccrt_type_get_num_args( t);
lccrt_type_ptr t0 = lccrt_type_get_parent( t);
if ( lccrt_type_is_void( t) )
{
tlen = snprintf( tname, 256, "void");
} else if ( lccrt_type_is_bool( t) )
{
tlen = snprintf( tname, 256, "bool");
} else if ( lccrt_type_is_ellipsis( t) )
{
tlen = snprintf( tname, 256, "...");
} else if ( lccrt_type_is_int( t) )
{
if ( lccrt_type_get_sign( t) )
{
tlen = snprintf( tname, 256, "i%d", (int)(8*lccrt_type_get_bytesize( t)));
} else
{
tlen = snprintf( tname, 256, "u%d", (int)(8*lccrt_type_get_bytesize( t)));
}
} else if ( lccrt_type_is_float( t) )
{
tlen = snprintf( tname, 256, "f%d", (int)(8*lccrt_type_get_bytesize( t)));
} else
{
is_simple = 0;
tlen = snprintf( tname, 256, "%%t%jd", irw->tident);
irw->tident++;
}
lccrt_assert( tlen <= 256);
lccrt_hash_set( e, (uintptr_t)lccrt_ctx_copy_str( irw->ctx, tname));
if ( is_simple )
{
} else if ( lccrt_type_is_typename( t) )
{
char sa[256];
lccrt_type_ptr tp = lccrt_type_make_ptr_type( t);
sa[0] = 0;
if ( t0 )
{
snprintf( sa, 256, " .size(%jd) .align(%jd)", lccrt_type_get_bytesize( t0),
lccrt_type_get_bytealign( t0));
}
lccrt_printf( irw, "type %s = typename%s;\n", tname, sa);
lccrt_irwriter_define_type( irw, t, tp, 0, &tname0);
lccrt_printf( irw, "type %s = *%s;\n", tname0, tname);
#if 0
if ( t0
&& !is_pointer )
{
lccrt_irwriter_define_type( irw, t, t0, 0, &tname0);
lccrt_printf( irw, "typelink %s = %s;\n", tname, tname0);
lccrt_hash_push( irw->typelinks, (uintptr_t)t, 0);
}
#endif
} else if ( lccrt_type_is_pointer( t) )
{
lccrt_irwriter_define_type( irw, t, t0, 1, &tname0);
if ( !lccrt_type_is_typename( t0) )
{
lccrt_printf( irw, "type %s = *%s;\n", tname, tname0);
}
} else if ( lccrt_type_is_array( t) )
{
lccrt_irwriter_define_type( irw, t, t0, 0, &tname0);
lccrt_printf( irw, "type %s = [%jd]%s;\n", tname, tnum_args, tname0);
} else if ( lccrt_type_is_struct( t)
|| lccrt_type_is_union( t) )
{
int i;
const char *s = lccrt_type_is_union( t) ? "union" : "struct";
for ( i = 0; i < tnum_args; ++i )
{
lccrt_type_ptr ti = lccrt_type_get_arg( t, i);
ti = lccrt_type_get_parent( ti);
lccrt_irwriter_define_type( irw, t, ti, 0, 0);
}
lccrt_printf( irw, "type %s = %s", tname, s);
lccrt_printf( irw, " .size(%jd)", lccrt_type_get_bytesize( t));
lccrt_printf( irw, " .align(%jd)", lccrt_type_get_bytealign( t));
lccrt_printf( irw, " {");
for ( i = 0; i < tnum_args; ++i )
{
lccrt_type_ptr ti = lccrt_type_get_arg( t, i);
lccrt_type_ptr ti_p = lccrt_type_get_parent( ti);
uint64_t shift = lccrt_type_get_byteshift( ti);
uint64_t bitsize = lccrt_type_get_bitsubsize( ti);
uint64_t bitshift = lccrt_type_get_bitsubshift( ti);
if ( (i > 0) ) lccrt_printf( irw, ", ");
lccrt_printf( irw, "%s", lccrt_irwriter_get_type_ident( irw, ti_p));
lccrt_printf( irw, " .shift(%jd)", shift);
if ( (bitshift > 0) )
{
lccrt_printf( irw, " .bitshift(%jd)", bitshift);
lccrt_printf( irw, " .bitsize(%jd)", bitsize);
}
}
lccrt_printf( irw, "};\n");
} else if ( lccrt_type_is_function( t) )
{
int i;
lccrt_irwriter_define_type( irw, t, lccrt_type_get_parent( t), 0, &tname0);
for ( i = 0; i < tnum_args; ++i )
{
lccrt_irwriter_define_type( irw, t, lccrt_type_get_arg( t, i), 0, 0);
}
lccrt_printf( irw, "type %s = func (", tname);
for ( i = 0; i < tnum_args; ++i )
{
lccrt_type_ptr ti = lccrt_type_get_arg( t, i);
if ( (i > 0) ) lccrt_printf( irw, ", ");
lccrt_printf( irw, "%s", lccrt_irwriter_get_type_ident( irw, ti));
}
if ( lccrt_type_is_function_var_arg( t) )
{
if ( (tnum_args == 0) )
{
lccrt_printf( irw, "...");
} else
{
if ( !lccrt_type_is_ellipsis( lccrt_type_get_arg( t, tnum_args - 1)) )
{
lccrt_printf( irw, ", ...");
}
}
}
lccrt_printf( irw, ") -> %s;\n", tname0);
} else
{
lccrt_type_print( t, 1);
lccrt_assert( 0);
}
e = lccrt_hash_find( irw->ptypes, (uintptr_t)t);
} else
{
lccrt_type_ptr t0 = lccrt_type_get_parent( t);
if ( lccrt_type_is_typename( t)
&& !(t_src
&& (lccrt_type_is_function( t_src))) )
{
char *tname = (char *)lccrt_hash_get( e);
if ( 0 && t0
&& !is_pointer
&& !lccrt_hash_find( irw->typelinks, (uintptr_t)t) )
{
char *tname0 = 0;
lccrt_irwriter_define_type( irw, t, t0, 0, &tname0);
lccrt_printf( irw, "typelink %s = %s;\n", tname, tname0);
lccrt_hash_push( irw->typelinks, (uintptr_t)t, 0);
}
e = lccrt_hash_find( irw->ptypes, (uintptr_t)t);
}
}
if ( tnameout )
{
(*tnameout) = (char *)lccrt_hash_get( e);
}
return;
} /* lccrt_irwriter_define_type */
/**
* Печать для модуля представления всех типов.
*/
static void
lccrt_irwriter_print_types( lccrt_irwriter_t *irw)
{
lccrt_type_ptr t;
int fd = irw->fd;
lccrt_module_ptr m = irw->m;
// Печатаем определение типов.
for ( t = lccrt_module_get_first_type( m); t; t = lccrt_type_get_next_type( t) )
{
if ( lccrt_type_is_field( t) )
{
} else
{
lccrt_irwriter_define_type( irw, 0, t, 0, 0);
}
}
// Печатаем связки типов-имен с их базовыми типами.
for ( t = lccrt_module_get_first_type( m); t; t = lccrt_type_get_next_type( t) )
{
if ( lccrt_type_is_typename( t) )
{
lccrt_type_ptr t0 = lccrt_type_get_parent( t);
if ( t0 )
{
lccrt_printf( irw, "typelink %s = %s;\n",
lccrt_irwriter_get_type_ident( irw, t),
lccrt_irwriter_get_type_ident( irw, t0));
}
}
}
lccrt_printf( irw, "\n");
return;
} /* lccrt_irwriter_print_types */
/**
* Печать сокращенных имен глобальных переменных и функций из представления модуля.
*/
static void
lccrt_irwriter_print_names( lccrt_irwriter_t *irw)
{
lccrt_var_ptr v;
lccrt_function_ptr g;
char nname[256];
lccrt_he_ptr e;
int fd = irw->fd;
lccrt_module_ptr m = irw->m;
for ( v = lccrt_module_get_first_var( m); v; v = lccrt_var_get_next_var( v) )
{
snprintf( nname, 256, "@n%jd", irw->nident);
irw->nident++;
e = lccrt_hash_push( irw->snames, (uintptr_t)v, 0);
lccrt_hash_set( e, (uintptr_t)lccrt_ctx_copy_str( irw->ctx, nname));
lccrt_printf( irw, "name %s = ", nname);
lccrt_print_ident( irw, lccrt_var_get_name( v));
lccrt_printf( irw, ";\n");
}
for ( g = lccrt_module_get_first_func( m); g; g = lccrt_function_get_next_func( g) )
{
snprintf( nname, 256, "@n%jd", irw->nident);
irw->nident++;
e = lccrt_hash_push( irw->snames, (uintptr_t)g, 0);
lccrt_hash_set( e, (uintptr_t)lccrt_ctx_copy_str( irw->ctx, nname));
lccrt_printf( irw, "name %s = ", nname);
lccrt_print_ident( irw, lccrt_function_get_name( g));
lccrt_printf( irw, ";\n");
}
lccrt_printf( irw, "\n");
return;
} /* lccrt_irwriter_print_names */
/**
* Печать списка ссылок на метаданные как атрибуты.
*/
static void
lccrt_irwriter_print_attr_einfo_list( lccrt_irwriter_t *irw, lccrt_einfo_link_ptr elink0)
{
lccrt_einfo_link_ptr elink;
lccrt_einfo_link_ptr prev = 0;
if ( elink0 )
{
// Проходимся по списку метаданных в обратном порядке.
for ( elink = elink0; elink->next; elink = elink->next ) ;
lccrt_printf( irw, " .einfo(\"");
for ( ; elink ; elink = elink->prev )
{
lccrt_einfo_category_t eic = elink->ident;
lccrt_einfo_handle_t eih = elink->value;
lccrt_he_ptr he = lccrt_hash_find( irw->einfos, (uintptr_t)eih.data.ref);
if ( prev ) lccrt_printf( irw, ",");
lccrt_printf( irw, "%%c%jd:%%e%jd", eic.id, lccrt_hash_get( he));
prev = elink;
}
lccrt_printf( irw, "\")");
}
return;
} /* lccrt_irwriter_print_attr_einfo_list */
/**
* Печать инициализатора переменной.
*/
static void
lccrt_irwriter_print_varinit( lccrt_irwriter_t *irw, lccrt_varinit_ptr vi)
{
int64_t i;
int fd = irw->fd;
const char *vn = 0;
lccrt_type_ptr t = lccrt_varinit_get_type( vi);
int64_t num_elems = lccrt_varinit_get_num_elems( vi);
lccrt_varinit_inittype_t vitype = lccrt_varinit_get_inittype( vi);
lccrt_printf( irw, "%s ", lccrt_irwriter_get_type_ident( irw, t));
switch ( vitype )
{
case LCCRT_VARINIT_ZERO:
lccrt_printf( irw, "zeroinit");
break;
case LCCRT_VARINIT_HEX:
lccrt_printf( irw, "0x%jx", lccrt_varinit_get_hex64( vi));
break;
case LCCRT_VARINIT_STR:
lccrt_print_escaped_bytearray( irw, num_elems, lccrt_varinit_get_str( vi));
break;
case LCCRT_VARINIT_ADDR_VAR:
case LCCRT_VARINIT_ADDR_FUNC:
if ( vitype == LCCRT_VARINIT_ADDR_VAR ) {
vn = lccrt_irwriter_get_name_ident( irw, lccrt_varinit_get_addr_var( vi));
} else {
vn = lccrt_irwriter_get_name_ident( irw, lccrt_varinit_get_addr_func( vi));
}
if ( num_elems >= 0 ) {
lccrt_printf( irw, "&%s+%jd", vn, num_elems);
} else {
lccrt_printf( irw, "&%s%jd", vn, num_elems);
}
break;
case LCCRT_VARINIT_ARR:
lccrt_printf( irw, "{");
for ( i = 0; i < num_elems; ++i )
{
if ( (i > 0) ) lccrt_printf( irw, ",");
lccrt_irwriter_print_varinit( irw, lccrt_varinit_get_elem( vi, i));
}
lccrt_printf( irw, "}");
break;
default:
lccrt_assert( 0);
break;
}
return;
} /* lccrt_irwriter_print_varinit */
/**
* Печать глобальных переменных из представления модуля.
*/
static void
lccrt_irwriter_print_gvars( lccrt_irwriter_t *irw)
{
lccrt_var_ptr v;
lccrt_he_ptr e;
int fd = irw->fd;
lccrt_module_ptr m = irw->m;
for ( v = lccrt_module_get_first_var( m); v; v = lccrt_var_get_next_var( v) )
{
lccrt_type_ptr t = lccrt_var_get_type( v);
const char *asm_name = lccrt_var_get_asm_name( v);
const char *comdat = lccrt_var_get_comdat( v);
const char *section = lccrt_var_get_section( v);
lccrt_link_t link = lccrt_var_get_link( v);
int64_t align = lccrt_var_get_align( v);
lccrt_link_visibility_t vis = lccrt_link_get_vis( link);
lccrt_link_tls_t tls = lccrt_link_get_tls( link);
lccrt_varinit_ptr vi = lccrt_var_get_init_value( v);
lccrt_printf( irw, "var ");
lccrt_print_ident( irw, lccrt_var_get_name( v));
lccrt_printf( irw, " : %s", lccrt_irwriter_get_type_ident( irw, t));
if ( asm_name
&& (strcmp( asm_name, lccrt_var_get_name( v)) != 0) )
{
lccrt_print_attr_string( irw, ".asm", asm_name);
}
if ( (align > 1) ) lccrt_printf( irw, " .align(%jd)", align);
if ( lccrt_link_is_alias( link) ) lccrt_printf( irw, " .alias");
if ( lccrt_link_is_const( link) ) lccrt_printf( irw, " .const");
if ( lccrt_var_get_attr_common( v) ) lccrt_printf( irw, " .common");
if ( lccrt_var_get_attr_used( v) ) lccrt_printf( irw, " .used");
lccrt_printf( irw, " .loc(%s)", lccrt_get_loc_str( lccrt_var_get_loc( v)));
lccrt_printf( irw, " .bind(%s)", lccrt_get_bnd_str( lccrt_link_get_bnd( link)));
if ( (vis != LCCRT_LINK_VIS_DEFAULT) ) lccrt_printf( irw, " .vis(%s)", lccrt_get_vis_str( vis));
if ( (tls != LCCRT_LINK_TLS_NO) ) lccrt_printf( irw, " .tls(%s)", lccrt_get_tls_str( tls));
if ( section ) lccrt_print_attr_string( irw, ".section", section);
if ( comdat ) lccrt_print_attr_string( irw, ".comdat", comdat);
lccrt_irwriter_print_attr_einfo_list( irw, v->einfo);
if ( vi )
{
lccrt_printf( irw, " = ");
lccrt_irwriter_print_varinit( irw, vi);
}
lccrt_printf( irw, ";\n");
}
lccrt_printf( irw, "\n");
return;
} /* lccrt_irwriter_print_gvars */
/**
* Для операций с результатом печать начальной части записи результата.
*/
static void
lccrt_irwriter_print_oper_define( lccrt_irwriter_t *irw, lccrt_oper_ptr inst)
{
int fd = irw->fd;
lccrt_oper_name_t inst_name = lccrt_oper_get_name( inst);
if ( lccrt_oper_name_is_res( inst_name) )
{
lccrt_var_ptr res = lccrt_oper_get_res( inst);
lccrt_print_ident( irw, lccrt_var_get_name( res));
lccrt_printf( irw, " = ");
}
return;
} /* lccrt_irwriter_print_oper_define */
/**
* Простой способ печати операции.
*/
static void
lccrt_irwriter_print_oper_simple( lccrt_irwriter_t *irw, lccrt_oper_ptr inst, const char *name)
{
int i;
int fd = irw->fd;
int num_args = lccrt_oper_get_num_args( inst);
lccrt_oper_name_t inst_name = lccrt_oper_get_name( inst);
lccrt_printf( irw, " ");
lccrt_irwriter_print_oper_define( irw, inst);
lccrt_printf( irw, "%s", name);
if ( lccrt_oper_is_atomic( inst) ) lccrt_printf( irw, " .atomic");
if ( lccrt_oper_is_volatile( inst) ) lccrt_printf( irw, " .volatile");
if ( lccrt_oper_is_cleanup( inst) ) lccrt_printf( irw, " .cleanup");
for ( i = 0; i < num_args; ++i )
{
lccrt_printf( irw, (i == 0) ? " " : ", ");
if ( lccrt_oper_name_is_arg_var( inst_name, i) )
{
lccrt_var_ptr arg_var = lccrt_oper_get_arg_var( inst, i);
if ( arg_var )
{
lccrt_print_ident( irw, lccrt_var_get_name( arg_var));
} else
{
lccrt_printf( irw, "0");
}
} else
{
lccrt_oper_ptr arg_oper = lccrt_oper_get_arg_oper( inst, i);
lccrt_print_ident( irw, lccrt_oper_get_label( arg_oper));
}
}
return;
} /* lccrt_irwriter_print_oper_simple */
/**
* Простой способ печати операции.
*/
static void
lccrt_irwriter_print_oper_conv( lccrt_irwriter_t *irw, lccrt_oper_ptr inst, const char *name)
{
int fd = irw->fd;
int num_args = lccrt_oper_get_num_args( inst);
lccrt_oper_name_t inst_name = lccrt_oper_get_name( inst);
lccrt_type_ptr tr = lccrt_oper_get_res_type( inst);
lccrt_printf( irw, " ");
lccrt_irwriter_print_oper_define( irw, inst);
lccrt_printf( irw, "%s ", name);
lccrt_print_ident( irw, lccrt_var_get_name( lccrt_oper_get_arg_var( inst, 0)));
lccrt_printf( irw, " to %s", lccrt_irwriter_get_type_ident( irw, tr));
return;
} /* lccrt_irwriter_print_oper_conv */
/**
* Печать представления операции.
*/
static void
lccrt_irwriter_print_oper( lccrt_irwriter_t *irw, lccrt_oper_ptr inst)
{
int fd = irw->fd;
int is_label = 0;
switch ( lccrt_oper_get_name( inst) )
{
case LCCRT_OPER_LABEL:
is_label = 1;
lccrt_print_ident( irw, lccrt_oper_get_label( inst));
break;
case LCCRT_OPER_BRANCH:
lccrt_irwriter_print_oper_simple( irw, inst, "branch");
break;
case LCCRT_OPER_BRANCHIF:
lccrt_irwriter_print_oper_simple( irw, inst, "branchif");
break;
case LCCRT_OPER_SWITCH:
lccrt_irwriter_print_oper_simple( irw, inst, "switch");
break;
case LCCRT_OPER_VARPTR:
lccrt_irwriter_print_oper_simple( irw, inst, "varptr");
break;
case LCCRT_OPER_MOVE:
lccrt_irwriter_print_oper_simple( irw, inst, "move");
break;
case LCCRT_OPER_LOAD:
lccrt_irwriter_print_oper_simple( irw, inst, "load");
break;
case LCCRT_OPER_STORE:
lccrt_irwriter_print_oper_simple( irw, inst, "store");
break;
case LCCRT_OPER_ADD:
lccrt_irwriter_print_oper_simple( irw, inst, "add");
break;
case LCCRT_OPER_SUB:
lccrt_irwriter_print_oper_simple( irw, inst, "sub");
break;
case LCCRT_OPER_MUL:
lccrt_irwriter_print_oper_simple( irw, inst, "mul");
break;
case LCCRT_OPER_UDIV:
lccrt_irwriter_print_oper_simple( irw, inst, "udiv");
break;
case LCCRT_OPER_SDIV:
lccrt_irwriter_print_oper_simple( irw, inst, "sdiv");
break;
case LCCRT_OPER_UMOD:
lccrt_irwriter_print_oper_simple( irw, inst, "umod");
break;
case LCCRT_OPER_SMOD:
lccrt_irwriter_print_oper_simple( irw, inst, "smod");
break;
case LCCRT_OPER_SHL:
lccrt_irwriter_print_oper_simple( irw, inst, "shl");
break;
case LCCRT_OPER_SHR:
lccrt_irwriter_print_oper_simple( irw, inst, "shr");
break;
case LCCRT_OPER_SAR:
lccrt_irwriter_print_oper_simple( irw, inst, "sar");
break;
case LCCRT_OPER_AND:
lccrt_irwriter_print_oper_simple( irw, inst, "and");
break;
case LCCRT_OPER_OR:
lccrt_irwriter_print_oper_simple( irw, inst, "or");
break;
case LCCRT_OPER_XOR:
lccrt_irwriter_print_oper_simple( irw, inst, "xor");
break;
case LCCRT_OPER_FNEG:
lccrt_irwriter_print_oper_simple( irw, inst, "fneg");
break;
case LCCRT_OPER_FADD:
lccrt_irwriter_print_oper_simple( irw, inst, "fadd");
break;
case LCCRT_OPER_FSUB:
lccrt_irwriter_print_oper_simple( irw, inst, "fsub");
break;
case LCCRT_OPER_FMUL:
lccrt_irwriter_print_oper_simple( irw, inst, "fmul");
break;
case LCCRT_OPER_FDIV:
lccrt_irwriter_print_oper_simple( irw, inst, "fdiv");
break;
case LCCRT_OPER_CALLPROC:
case LCCRT_OPER_CALLFUNC:
lccrt_irwriter_print_oper_simple( irw, inst, "call");
break;
case LCCRT_OPER_INVOKEPROC:
case LCCRT_OPER_INVOKEFUNC:
lccrt_irwriter_print_oper_simple( irw, inst, "invoke");
break;
case LCCRT_OPER_LANDINGPAD:
lccrt_irwriter_print_oper_simple( irw, inst, "landingpad");
break;
case LCCRT_OPER_RET:
case LCCRT_OPER_RETVAL:
lccrt_irwriter_print_oper_simple( irw, inst, "ret");
break;
case LCCRT_OPER_ELEMPTR:
lccrt_irwriter_print_oper_simple( irw, inst, "elemptr");
break;
case LCCRT_OPER_ELEMREAD:
lccrt_irwriter_print_oper_simple( irw, inst, "elemread");
break;
case LCCRT_OPER_ELEMWRITE:
lccrt_irwriter_print_oper_simple( irw, inst, "elemwrite");
break;
case LCCRT_OPER_SELECT:
lccrt_irwriter_print_oper_simple( irw, inst, "select");
break;
case LCCRT_OPER_SHUFFLE:
lccrt_irwriter_print_oper_simple( irw, inst, "shuffle");
break;
case LCCRT_OPER_CMP:
lccrt_irwriter_print_oper_simple( irw, inst, "cmp");
break;
case LCCRT_OPER_BITCAST:
lccrt_irwriter_print_oper_conv( irw, inst, "bitcast");
break;
case LCCRT_OPER_SEXT:
lccrt_irwriter_print_oper_conv( irw, inst, "sext");
break;
case LCCRT_OPER_ZEXT:
lccrt_irwriter_print_oper_conv( irw, inst, "zext");
break;
case LCCRT_OPER_TRUNC:
lccrt_irwriter_print_oper_conv( irw, inst, "trunc");
break;
case LCCRT_OPER_FPTOFP:
lccrt_irwriter_print_oper_conv( irw, inst, "fptofp");
break;
case LCCRT_OPER_FPTOUI:
lccrt_irwriter_print_oper_conv( irw, inst, "fptoui");
break;
case LCCRT_OPER_FPTOSI:
lccrt_irwriter_print_oper_conv( irw, inst, "fptosi");
break;
case LCCRT_OPER_UITOFP:
lccrt_irwriter_print_oper_conv( irw, inst, "uitofp");
break;
case LCCRT_OPER_SITOFP:
lccrt_irwriter_print_oper_conv( irw, inst, "sitofp");
break;
case LCCRT_OPER_ALLOCA:
lccrt_irwriter_print_oper_conv( irw, inst, "alloca");
break;
case LCCRT_OPER_VA_ARG:
lccrt_irwriter_print_oper_conv( irw, inst, "vaarg");
break;
default:
//lccrt_oper_print( inst, 1);
lccrt_assert( 0);
break;
}
lccrt_irwriter_print_attr_einfo_list( irw, inst->einfo);
if ( is_label )
{
lccrt_printf( irw, ":\n");
} else
{
lccrt_printf( irw, ";\n");
}
return;
} /* lccrt_irwriter_print_oper */
/**
* Печать атрибутов функции.
*/
static void
lccrt_irwriter_print_func_attrs( lccrt_irwriter_t *irw, lccrt_function_ptr g)
{
int fd = irw->fd;
const char *asm_name = lccrt_function_get_asm_name( g);
const char *comdat = lccrt_function_get_comdat( g);
const char *section = lccrt_function_get_section( g);
lccrt_link_t link = lccrt_function_get_link( g);
lccrt_link_visibility_t vis = lccrt_link_get_vis( link);
if ( asm_name
&& (strcmp( asm_name, lccrt_function_get_name( g)) != 0) )
{
lccrt_print_attr_string( irw, ".asm", asm_name);
}
if ( lccrt_function_is_declaration( g) ) lccrt_printf( irw, " .extern");
lccrt_printf( irw, " .bind(%s)", lccrt_get_bnd_str( lccrt_link_get_bnd( link)));
if ( (vis != LCCRT_LINK_VIS_DEFAULT) ) lccrt_printf( irw, " .vis(%s)", lccrt_get_vis_str( vis));
if ( lccrt_function_get_attr_used( g) ) lccrt_printf( irw, " .used");
if ( lccrt_function_get_attr_does_not_throw( g) ) lccrt_printf( irw, " .nothrow");
if ( lccrt_function_get_attr_extern_inline( g) ) lccrt_printf( irw, " .extinline");
if ( lccrt_function_is_builtin( g) ) lccrt_printf( irw, " .builtin");
if ( section ) lccrt_print_attr_string( irw, ".section", section);
if ( comdat ) lccrt_print_attr_string( irw, ".comdat", comdat);
if ( (lccrt_function_get_init_type( g) == LCCRT_FUNC_INIT_CTOR) )
{
lccrt_printf( irw, " .ctor(%d)", lccrt_function_get_init_priority( g));
} else if ( (lccrt_function_get_init_type( g) == LCCRT_FUNC_INIT_DTOR) )
{
lccrt_printf( irw, " .dtor(%d)", lccrt_function_get_init_priority( g));
}
lccrt_irwriter_print_attr_einfo_list( irw, g->einfo);
return;
} /* lccrt_irwriter_print_func_attrs */
/**
* Печать глобальных переменных из представления модуля.
*/
static void
lccrt_irwriter_print_funcs( lccrt_irwriter_t *irw)
{
lccrt_function_ptr g;
lccrt_he_ptr e;
int fd = irw->fd;
lccrt_module_ptr m = irw->m;
for ( g = lccrt_module_get_first_func( m); g; g = lccrt_function_get_next_func( g) )
{
int i;
int num_args = lccrt_function_get_num_args( g);
lccrt_type_ptr t = lccrt_function_get_type( g);
lccrt_type_ptr t0 = lccrt_type_get_parent( t);
lccrt_printf( irw, "func ");
lccrt_print_ident( irw, lccrt_function_get_name( g));
lccrt_printf( irw, " : (");
for ( i = 0; i < num_args; ++i )
{
lccrt_var_ptr v = lccrt_function_get_arg( g, i);
lccrt_type_ptr ti = lccrt_type_get_arg( t, i);
if ( (i > 0) ) lccrt_printf( irw, ", ");
if ( v )
{
lccrt_print_ident( irw, lccrt_var_get_name( v));
lccrt_printf( irw, " ");
if ( lccrt_var_get_attr_restrict( v) ) lccrt_printf( irw, " .restrict");
}
lccrt_printf( irw, ": ");
lccrt_printf( irw, "%s", lccrt_irwriter_get_type_ident( irw, ti));
}
if ( lccrt_function_is_var_arg( g) )
{
if ( (num_args > 0) ) lccrt_printf( irw, ", ");
lccrt_printf( irw, ": ...");
}
lccrt_printf( irw, ") -> ");
lccrt_printf( irw, "%s", lccrt_irwriter_get_type_ident( irw, t0));
lccrt_irwriter_print_func_attrs( irw, g);
if ( lccrt_function_is_declaration( g) )
{
lccrt_printf( irw, ";\n");
} else
{
lccrt_var_ptr v;
lccrt_oper_ptr inst;
lccrt_printf( irw, "\n{\n");
for ( v = lccrt_function_get_first_var( g);
v;
v = lccrt_var_get_next_var( v) )
{
lccrt_var_loc_t loc = lccrt_var_get_loc( v);
const char *vname = lccrt_var_get_name( v);
lccrt_type_ptr vtype = lccrt_var_get_type( v);
char *vtid = lccrt_irwriter_get_type_ident( irw, vtype);
if ( (loc == LCCRT_VAR_LOC_LOCAL) )
{
lccrt_printf( irw, " loc ");
lccrt_print_ident( irw, vname);
lccrt_printf( irw, " : %s;\n", vtid);
} else if ( (loc == LCCRT_VAR_LOC_ASM) )
{
lccrt_printf( irw, " locasm ");
lccrt_print_ident( irw, vname);
lccrt_printf( irw, " : %s;\n", vtid);
}
}
for ( inst = lccrt_function_get_first_oper( g);
inst;
inst = lccrt_oper_get_next( inst) )
{
lccrt_irwriter_print_oper( irw, inst);
}
lccrt_printf( irw, "}\n");
}
lccrt_printf( irw, "\n");
}
return;
} /* lccrt_irwriter_print_funcs */
/**
* Печатаем дескриптор описания типа метаданных.
*/
static void
lccrt_irwriter_print_einfo_tydescr_ident( lccrt_irwriter_t *irw, lccrt_einfo_tydescr_ptr etyde)
{
if ( lccrt_einfo_is_tydescr_i64( etyde) )
{
lccrt_printf( irw, "i64");
} else if ( lccrt_einfo_is_tydescr_raw( etyde) )
{
lccrt_printf( irw, "raw");
} else
{
lccrt_he_ptr he = lccrt_hash_find( irw->eitydes, (uintptr_t)etyde);
lccrt_printf( irw, "%%s%jd", lccrt_hash_get( he));
}
return;
} /* lccrt_irwriter_print_einfo_tydescr_ident */
/**
* Печатаем описание типа метаданных.
*/
static void
lccrt_irwriter_print_einfo_tydescr( lccrt_irwriter_t *irw, int ident, lccrt_einfo_tydescr_ptr etyde)
{
int i;
if ( (etyde->type == LCCRT_EINFO_ARRAY) )
{
lccrt_printf( irw, "eityde %%s%d = array ", ident);
lccrt_assert( etyde->num_flds = 1);
lccrt_irwriter_print_einfo_tydescr_ident( irw, etyde->types[0]);
lccrt_printf( irw, ";\n");
} else if ( (etyde->type == LCCRT_EINFO_UNION) )
{
lccrt_printf( irw, "eityde %%s%d = union {", ident);
for ( i = 0; i < etyde->num_flds; ++i )
{
if ( (i > 0) ) lccrt_printf( irw, ",");
lccrt_irwriter_print_einfo_tydescr_ident( irw, etyde->types[i]);
}
lccrt_printf( irw, "};\n");
} else if ( (etyde->type == LCCRT_EINFO_STRUCT) )
{
lccrt_printf( irw, "eityde %%s%d = struct ", ident);
lccrt_print_ident( irw, etyde->self_name);
lccrt_printf( irw, " {");
for ( i = 0; i < etyde->num_flds; ++i )
{
if ( (i > 0) ) lccrt_printf( irw, ",");
lccrt_print_ident( irw, etyde->flds[i]);
lccrt_printf( irw, ":");
lccrt_irwriter_print_einfo_tydescr_ident( irw, etyde->types[i]);
}
lccrt_printf( irw, "};\n");
} else
{
lccrt_assert( 0);
}
return;
} /* lccrt_irwriter_print_einfo_tydescr */
/**
* Печать идетификатора блока метаданных.
*/
static void
lccrt_irwriter_print_einfo_block_ident( lccrt_irwriter_t *irw, lccrt_einfo_handle_t ehdl)
{
if ( (ehdl.type == LCCRT_EINFO_NULL) )
{
lccrt_printf( irw, "nil");
} else if ( (ehdl.type == LCCRT_EINFO_INT64) )
{
lccrt_printf( irw, "0x%jx", ehdl.data.i64);
} else
{
lccrt_einfo_block_ptr eblock = ehdl.data.ref;
lccrt_he_ptr he = lccrt_hash_find( irw->einfos, (intptr_t)eblock);
lccrt_printf( irw, "%%e%d", (int)lccrt_hash_get( he));
}
return;
} /* lccrt_irwriter_print_einfo_block_ident */
/**
* Печатаем значение блока метаданных.
*/
static void
lccrt_irwriter_print_einfo_block( lccrt_irwriter_t *irw, int ident, lccrt_einfo_block_ptr eblck)
{
int i;
lccrt_printf( irw, "eidef %%e%d = ", ident);
lccrt_irwriter_print_einfo_tydescr_ident( irw, eblck->tydescr);
lccrt_printf( irw, " {");
if ( (eblck->type == LCCRT_EINFO_ARRAY)
|| (eblck->type == LCCRT_EINFO_STRUCT) )
{
for ( i = 0; i < eblck->num_args; ++i )
{
if ( (i > 0) ) lccrt_printf( irw, ",");
lccrt_irwriter_print_einfo_block_ident( irw, eblck->data.elems[i]);
}
} else if ( (eblck->type == LCCRT_EINFO_RAW) )
{
int is_str = 1;
int len = eblck->num_args;
const uint8_t *rdata = eblck->data.rdata;
if ( (rdata[len - 1] == 0) )
{
int escape_cnt = 0;
for ( i = 0; i < len; ++i )
{
int c = rdata[i];
if ( !isprint( c)
|| (c == '\\')
|| (c == '"') )
{
escape_cnt++;
}
}
if ( (len - 1 + 2*escape_cnt <= 2*len) )
{
is_str = 1;
}
}
if ( is_str )
{
lccrt_print_escaped_string( irw, rdata);
} else
{
lccrt_assert( 0);
}
} else
{
lccrt_assert( 0);
}
lccrt_printf( irw, "};\n");
return;
} /* lccrt_irwriter_print_einfo_block */
/**
* Печатаем метаданные модуля.
*/
static void
lccrt_irwriter_print_einfo( lccrt_irwriter_t *irw)
{
int64_t i;
lccrt_hash_entry_ptr he;
lccrt_einfo_link_ptr elink;
lccrt_module_ptr m = irw->m;
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
// Печатаем категории мета-данных.
if ( lccrt_hash_first( m->einfo_cats) )
{
for ( he = lccrt_hash_first( m->einfo_cats); he; he = lccrt_hash_next( he) )
{
intptr_t ecat = lccrt_hash_get( he);
const char *ecat_name = (char *)lccrt_hash_get_key( he);
lccrt_printf( irw, "eicat %%c%jd = %s;\n", ecat, ecat_name);
}
lccrt_printf( irw, "\n");
}
// Печатаем определения описания типов мета-данных.
if ( lccrt_hash_length( irw->eitydes ) )
{
int tlen = lccrt_hash_length( irw->eitydes);
lccrt_einfo_tydescr_ptr *types = lccrt_ctx_mallocn( ctx, lccrt_einfo_tydescr_ptr, tlen);
for ( he = lccrt_hash_first( irw->eitydes); he; he = lccrt_hash_next( he) )
{
types[lccrt_hash_get( he)] = (lccrt_einfo_tydescr_ptr)lccrt_hash_get_key( he);
}
for ( i = 0; i < tlen; ++i )
{
if ( !lccrt_einfo_is_tydescr_i64( types[i])
&& !lccrt_einfo_is_tydescr_raw( types[i]) )
{
lccrt_irwriter_print_einfo_tydescr( irw, i, types[i]);
}
}
lccrt_printf( irw, "\n");
lccrt_ctx_free( ctx, types);
}
// Печатаем значения блоков мета-данных.
if ( lccrt_hash_length( irw->einfos) )
{
int blen = lccrt_hash_length( irw->einfos);
lccrt_einfo_block_ptr *blocks = lccrt_ctx_mallocn( ctx, lccrt_einfo_block_ptr, blen);
for ( he = lccrt_hash_first( irw->einfos); he; he = lccrt_hash_next( he) )
{
blocks[lccrt_hash_get( he)] = (lccrt_einfo_block_ptr)lccrt_hash_get_key( he);
}
for ( i = 0; i < blen; ++i )
{
lccrt_irwriter_print_einfo_block( irw, i, blocks[i]);
}
lccrt_printf( irw, "\n");
lccrt_ctx_free( ctx, blocks);
}
for ( elink = irw->m->einfo; elink; elink = elink->next )
{
lccrt_printf( irw, "eiroot %%c%jd ", elink->ident);
//lccrt_irwriter_print_einfo_tydescr_ident( irw, elink->value.data.ref->tydescr);
//lccrt_printf( irw, " ");
lccrt_irwriter_print_einfo_block_ident( irw, elink->value);
lccrt_printf( irw, ";\n");
}
if ( irw->m->einfo ) lccrt_printf( irw, "\n");
return;
} /* lccrt_irwriter_print_einfo */
/**
* Печать для представления модуля конфигурации компиляции.
*/
static void
lccrt_irwriter_print_config( lccrt_irwriter_t *irw, lccrt_asm_compile_config_t *acc)
{
int fd = irw->fd;
lccrt_print_define_string( irw, "config target = ", acc->target);
lccrt_print_define_string( irw, "config out_type = ", acc->out_type);
lccrt_printf( irw, "config opt_level = %d;\n", acc->opt_level);
lccrt_printf( irw, "config is_pic = %d;\n", acc->is_pic);
lccrt_printf( irw, "config pie_level = %d;\n", acc->pie_level);
lccrt_printf( irw, "config dbg_level = %d;\n", acc->dbg_level);
lccrt_printf( irw, "config function_sections = %d;\n", acc->function_sections);
lccrt_printf( irw, "config data_sections = %d;\n", acc->data_sections);
lccrt_printf( irw, "config asm_verbose = %d;\n", acc->asm_verbose);
lccrt_printf( irw, "config llvmir_embed_static_only = %d;\n", acc->is_llvmir_embed_static_only);
lccrt_print_define_string( irw, "config eh_personality = ", acc->eh_personality);
lccrt_print_define_string( irw, "config cpu_arch = ", acc->cpu_arch);
lccrt_print_define_string( irw, "config cflags = ", acc->cflags);
lccrt_printf( irw, "\n");
return;
} /* lccrt_irwriter_print_config */
/**
* Печать представления модуля в выходной поток данных.
*/
int
lccrt_module_print( lccrt_asm_compile_config_t *acc, lccrt_module_ptr m, int fd)
{
lccrt_he_ptr e;
int r = 0;
lccrt_irwriter_t irw = {};
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
const char *sasm = lccrt_module_get_inline_asm( m);
// Готовим данные.
irw.ctx = ctx;
irw.m = m;
irw.fd = fd;
irw.ptypes = lccrt_hash_new( ctx, LCCRT_HASH_KEY_INTPTR);
irw.snames = lccrt_hash_new( ctx, LCCRT_HASH_KEY_INTPTR);
irw.typelinks = lccrt_hash_new( ctx, LCCRT_HASH_KEY_INTPTR);
irw.einfos = lccrt_hash_new( ctx, LCCRT_HASH_KEY_INTPTR);
irw.eitydes = lccrt_hash_new( ctx, LCCRT_HASH_KEY_INTPTR);
lccrt_module_einfo_number( m, irw.einfos, irw.eitydes);
lccrt_irwriter_print_config( &irw, acc);
// Печатаем глобальную ассемблерную вставку.
if ( sasm )
{
lccrt_printf( &irw, "asm(");
lccrt_print_escaped_string( &irw, sasm);
lccrt_printf( &irw, ");\n\n");
}
// Печатаем определение типов.
lccrt_irwriter_print_types( &irw);
// Печатаем сокращенные именования, чтобы не использовать потенциально длинные
// названия функций и переменных из-за C++-манглирования.
lccrt_irwriter_print_names( &irw);
// Печатаем глобальные переменные.
lccrt_irwriter_print_gvars( &irw);
// Печатаем функции.
lccrt_irwriter_print_funcs( &irw);
// Печатаем метаданные модуля.
lccrt_irwriter_print_einfo( &irw);
lccrt_printf( &irw, "\n");
// Удаляем таблицы вместе с данныим.
irw.ptypes = lccrt_delete_hash_with_data( ctx, irw.ptypes);
irw.snames = lccrt_delete_hash_with_data( ctx, irw.snames);
lccrt_hash_delete( irw.typelinks);
lccrt_hash_delete( irw.einfos);
lccrt_hash_delete( irw.eitydes);
return (r);
} /* lccrt_module_print */
/**
* Печать представления модуля в стандартный поток данных.
*/
int
lccrt_module_print_stdout( lccrt_asm_compile_config_t *acc, lccrt_module_ptr m)
{
int r = lccrt_module_print( acc, m, fileno( stdout));
return (r);
} /* lccrt_module_print_stdout */