Commit d13f67ce authored by Matthias Braun's avatar Matthias Braun
Browse files

introduce tarval_to_ascii and ascii_to_tarval and use it in irio

parent 9027d36c
......@@ -23,7 +23,7 @@
#include "irgmod.h"
#include "irflag_t.h"
#include "irgwalk.h"
#include "tv.h"
#include "tv_t.h"
#include "array.h"
#include "error.h"
#include "typerep.h"
......@@ -416,16 +416,12 @@ static void write_mode_ref(write_env_t *env, ir_mode *mode)
static void write_tarval(write_env_t *env, ir_tarval *tv)
{
write_mode_ref(env, get_tarval_mode(tv));
if (tv == tarval_bad) {
write_symbol(env, "bad");
} else {
fputs("0x", env->file);
char buf[1024];
tarval_snprintf(buf, sizeof(buf), tv);
fputs(buf, env->file);
fputc(' ', env->file);
}
ir_mode *mode = get_tarval_mode(tv);
write_mode_ref(env, mode);
char buf[128];
const char *ascii = ir_tarval_to_ascii(buf, sizeof(buf), tv);
fputs(ascii, env->file);
fputc(' ', env->file);
}
static void write_align(write_env_t *env, ir_align align)
......@@ -1608,12 +1604,7 @@ static ir_tarval *read_tarval(read_env_t *env)
{
ir_mode *tvmode = read_mode_ref(env);
char *str = read_word(env);
ir_tarval *tv;
if (strcmp(str, "bad") == 0)
return tarval_bad;
tv = new_tarval_from_str(str, strlen(str), tvmode);
if (tv == tarval_bad)
parse_error(env, "problem while parsing tarval '%s'\n", str);
ir_tarval *tv = ir_tarval_from_ascii(str, tvmode);
obstack_free(&env->obst, str);
return tv;
......
......@@ -1259,6 +1259,89 @@ int tarval_snprintf(char *buf, size_t len, ir_tarval *tv)
}
}
static char hexchar(unsigned val)
{
if (val < 10)
return val + '0';
return (val-10) + 'A';
}
static unsigned hexval(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
return (c - 'A')+10;
}
const char *ir_tarval_to_ascii(char *buf, size_t len, ir_tarval *tv)
{
ir_mode *mode = get_tarval_mode(tv);
switch (get_mode_sort(mode)) {
case irms_internal_boolean:
case irms_reference:
case irms_int_number:
return sc_print_buf(buf, len, tv->value, get_mode_size_bits(mode),
SC_HEX, 0);
case irms_float_number: {
/* fc_print is not specific enough for nans/infs, so we simply dump the
* bit representation in hex. */
unsigned size = get_mode_size_bytes(mode);
for (size_t i = 0; i < size; ++i) {
uint8_t bits = get_tarval_sub_bits(tv, (int)i);
buf[i*2] = hexchar(bits & 0xf);
buf[i*2+1] = hexchar(bits >> 4);
}
buf[size*2] = '\0';
return buf;
}
case irms_data:
case irms_auxiliary:
if (tv == tarval_bad)
return "bad";
else if (tv == tarval_undefined)
return "undefined";
else if (tv == tarval_reachable)
return "reachable";
else if (tv == tarval_unreachable)
return "unreachable";
break;
}
panic("invalid tarval");
}
ir_tarval *ir_tarval_from_ascii(const char *buf, ir_mode *mode)
{
size_t len = strlen(buf);
switch (get_mode_sort(mode)) {
case irms_reference:
case irms_internal_boolean:
case irms_int_number:
return new_integer_tarval_from_str(buf, len, 1, 16, mode);
case irms_float_number: {
unsigned size = get_mode_size_bytes(mode);
unsigned char *temp = ALLOCAN(unsigned char, size);
for (size_t i = 0; i < size; ++i) {
unsigned char val = hexval(buf[i*2]) | (hexval(buf[i*2+1]) << 4);
temp[i] = val;
}
fc_val_from_ieee754_buf(NULL, temp, get_descriptor(mode));
return get_tarval_from_fp_value(fc_get_buffer(), mode);
}
case irms_data:
case irms_auxiliary:
if (strcmp(buf, "bad") == 0)
return tarval_bad;
else if (strcmp(buf, "undefined") == 0)
return tarval_undefined;
else if (strcmp(buf, "reachable") == 0)
return tarval_reachable;
else if (strcmp(buf, "unreachable") == 0)
return tarval_unreachable;
break;
}
panic("invalid mode for tarval_from_ascii");
}
char *get_tarval_bitpattern(ir_tarval *tv)
{
int n = get_mode_size_bits(tv->mode);
......
......@@ -116,6 +116,20 @@ static inline int _is_tarval(const void *thing)
return get_kind(thing) == k_tarval;
}
/**
* Converts tarval to ascii representation (in contrast to tarval_snprintf()
* this is meant to be machine readble).
* If the output is bigger than buf_len the behaviour is undefined. The
* final value may be near the end of the buffer, use the return value!
*/
const char *ir_tarval_to_ascii(char *buf, size_t buf_len, ir_tarval *tv);
/**
* Converts ascii representation to tarval with specified mode. Compatible with
* ir_tarval_to_ascii().
*/
ir_tarval *ir_tarval_from_ascii(const char *buf, ir_mode *mode);
uint64_t get_tarval_uint64(ir_tarval *tv);
bool tarval_is_uint64(ir_tarval *tv);
......
#include "tv_t.h"
#include "irprintf.h"
#include "firm.h"
#include <assert.h>
#include <float.h>
static char buf[1024];
static void test_tv(ir_tarval *tv)
{
const char *res = ir_tarval_to_ascii(buf, sizeof(buf), tv);
ir_tarval *back = ir_tarval_from_ascii(res, get_tarval_mode(tv));
if (tv != back) {
ir_printf("%T [mode %s]\n", tv, get_mode_name(get_tarval_mode(tv)));
printf(" encoded: %s\n", res);
assert(tv == back);
}
}
static void test_mode(ir_mode *mode)
{
test_tv(get_mode_null(mode));
test_tv(get_mode_one(mode));
if (mode_is_signed(mode))
test_tv(get_mode_minus_one(mode));
test_tv(get_mode_min(mode));
test_tv(get_mode_max(mode));
if (mode_is_float(mode)) {
test_tv(get_mode_infinite(mode));
test_tv(tarval_neg(get_mode_infinite(mode)));
test_tv(get_mode_NAN(mode));
if (mode == mode_F) {
test_tv(new_tarval_from_double(FLT_MIN, mode));
test_tv(new_tarval_from_double(FLT_EPSILON, mode));
}
if (mode == mode_D) {
test_tv(new_tarval_from_double(DBL_MIN, mode));
test_tv(new_tarval_from_double(DBL_EPSILON, mode));
}
test_tv(new_tarval_from_str("-4.3", 4, mode));
test_tv(new_tarval_from_str("84.1", 4, mode));
} else {
test_tv(get_mode_all_one(mode));
}
}
int main(void)
{
ir_init();
test_mode(mode_Bs);
test_mode(mode_Bu);
test_mode(mode_Hs);
test_mode(mode_Hu);
test_mode(mode_Is);
test_mode(mode_Iu);
test_mode(mode_Ls);
test_mode(mode_Lu);
test_mode(mode_F);
test_mode(mode_D);
test_mode(mode_P);
ir_mode *mode_E = new_float_mode("E", irma_x86_extended_float, 15, 64,
ir_overflow_indefinite);
test_mode(mode_E);
test_tv(tarval_bad);
test_tv(tarval_undefined);
test_tv(tarval_reachable);
test_tv(tarval_unreachable);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment