Skip to content

Commit

Permalink
Use an intermediate representation to reinterpret the value in Target…
Browse files Browse the repository at this point in the history
…::paintAsType
  • Loading branch information
ibuclaw committed Jul 23, 2014
1 parent f740f0d commit 9bc842e
Showing 1 changed file with 91 additions and 21 deletions.
112 changes: 91 additions & 21 deletions src/target.c
Expand Up @@ -198,6 +198,88 @@ Type *Target::va_listType()
}
}

/******************************
* Private helpers for Target::paintAsType.
*/

// Write the integer value of 'e' into a unsigned byte buffer.
static void encodeInteger(Expression *e, unsigned char *buffer)
{
dinteger_t value = e->toInteger();
int size = e->type->size();

for (int p = 0; p < size; p++)
{
int offset = p; // Would be (size - 1) - p; on BigEndian
buffer[offset] = ((value >> (p * 8)) & 0xFF);
}
}

// Write the bytes encoded in 'buffer' into an integer and returns
// the value as a new IntegerExp.
static Expression *decodeInteger(Loc loc, Type *type, unsigned char *buffer)
{
dinteger_t value = 0;
int size = type->size();

for (int p = 0; p < size; p++)
{
int offset = p; // Would be (size - 1) - p; on BigEndian
value |= ((dinteger_t)buffer[offset] << (p * 8));
}

return new IntegerExp(loc, value, type);
}

// Write the real value of 'e' into a unsigned byte buffer.
static void encodeReal(Expression *e, unsigned char *buffer)
{
switch (e->type->ty)
{
case Tfloat32:
{
float *p = (float *)buffer;
*p = (float)e->toReal();
break;
}
case Tfloat64:
{
double *p = (double *)buffer;
*p = (double)e->toReal();
break;
}
default:
assert(0);
}
}

// Write the bytes encoded in 'buffer' into a longdouble and returns
// the value as a new RealExp.
static Expression *decodeReal(Loc loc, Type *type, unsigned char *buffer)
{
longdouble value;

switch (type->ty)
{
case Tfloat32:
{
float *p = (float *)buffer;
value = ldouble(*p);
break;
}
case Tfloat64:
{
double *p = (double *)buffer;
value = ldouble(*p);
break;
}
default:
assert(0);
}

return new RealExp(loc, value, type);
}

/******************************
* Encode the given expression, which is assumed to be an rvalue literal
* as another type for use in CTFE.
Expand All @@ -206,55 +288,43 @@ Type *Target::va_listType()

Expression *Target::paintAsType(Expression *e, Type *type)
{
union
{
d_int32 int32value;
d_int64 int64value;
float float32value;
double float64value;
} u;
// We support up to 512-bit values.
unsigned char buffer[64];

memset(buffer, 0, sizeof(buffer));
assert(e->type->size() == type->size());

// Write the expression into the buffer.
switch (e->type->ty)
{
case Tint32:
case Tuns32:
u.int32value = (d_int32)e->toInteger();
break;

case Tint64:
case Tuns64:
u.int64value = (d_int64)e->toInteger();
encodeInteger(e, buffer);
break;

case Tfloat32:
u.float32value = e->toReal();
break;

case Tfloat64:
u.float64value = e->toReal();
encodeReal(e, buffer);
break;

default:
assert(0);
}

// Interpret the buffer as a new type.
switch (type->ty)
{
case Tint32:
case Tuns32:
return new IntegerExp(e->loc, u.int32value, type);

case Tint64:
case Tuns64:
return new IntegerExp(e->loc, u.int64value, type);
return decodeInteger(e->loc, type, buffer);

case Tfloat32:
return new RealExp(e->loc, ldouble(u.float32value), type);

case Tfloat64:
return new RealExp(e->loc, ldouble(u.float64value), type);
return decodeReal(e->loc, type, buffer);

default:
assert(0);
Expand Down

0 comments on commit 9bc842e

Please sign in to comment.