1487 lines
46 KiB
C
1487 lines
46 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_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 */
|