Skip to content
This repository has been archived by the owner on Jun 20, 2019. It is now read-only.

Commit

Permalink
Add backend support for painting to/from array literals in CTFE.
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuclaw committed Oct 10, 2013
1 parent b2a4421 commit 262a5bd
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 41 deletions.
6 changes: 6 additions & 0 deletions gcc/d/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2013-10-10 Iain Buclaw <ibuclaw@gdcproject.org>

* d-builtins.c(gcc_cst_to_d_expr): Add support for VECTOR_CST to
Expression conversion.
(d_gcc_paint_type): Add support for painting to/from array literals.

2013-10-01 Iain Buclaw <ibuclaw@gdcproject.org>

* d-objfile.cc(cvtLocToloc_t): Rename to get_linemap.
Expand Down
125 changes: 101 additions & 24 deletions gcc/d/d-builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -718,13 +718,33 @@ gcc_cst_to_d_expr (tree cst)
size_t len = TREE_STRING_LENGTH (cst);
return new StringExp (Loc(), CONST_CAST (void *, string), len);
}
else if (code == VECTOR_CST)
{
dinteger_t nunits = VECTOR_CST_NELTS (cst);
Expressions *elements = new Expressions;
elements->setDim (nunits);

for (size_t i = 0; i < nunits; i++)
{
Expression *elem = gcc_cst_to_d_expr (VECTOR_CST_ELT (cst, i));
if (elem == NULL)
return NULL;

(*elements)[i] = elem;
}

Expression *e = new ArrayLiteralExp (Loc(), elements);
e->type = ((TypeVector *) type)->basetype;

return new VectorExp (Loc(), e, type);
}
}

return NULL;
}

// Helper for d_gcc_eval_builtin. Evaluate builtin D
// function BUILTIN whose argument list is ARGUMENTS.
// Return result; NULL if cannot evaluate it.
// Helper for d_gcc_eval_builtin. Evaluate builtin D function BUILTIN whose
// argument list is ARGUMENTS. Return result; NULL if cannot evaluate it.

Expression *
eval_builtin (Loc loc, BUILTIN builtin, Expressions *arguments)
Expand Down Expand Up @@ -827,7 +847,6 @@ eval_builtin (Loc loc, BUILTIN builtin, Expressions *arguments)
}

return e;

}

// Evaluate builtin D function FD whose argument list is ARGUMENTS.
Expand Down Expand Up @@ -859,27 +878,85 @@ d_gcc_eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
}
}

// Perform a reinterpret cast of EXPR to type TYPE for use in CTFE.
// The front end should have already ensured that EXPR is a constant,
// so we just lower the value to GCC and return the converted CST.

Expression *
d_gcc_paint_type (Expression *expr, Type *type)
{
/* We support up to 512-bit values. */
unsigned char buffer[64];
int len;
Expression *e;
tree cst;

if (type->isintegral())
Type *tb = type->toBasetype();

if (expr->type->isintegral())
cst = build_integer_cst (expr->toInteger(), expr->type->toCtype());
else if (expr->type->isfloating())
cst = build_float_cst (expr->toReal(), expr->type);
else if (expr->op == TOKarrayliteral)
{
// Build array as VECTOR_CST, assumes EXPR is constant.
Expressions *elements = ((ArrayLiteralExp *) expr)->elements;
vec<constructor_elt, va_gc> *elms = NULL;

vec_safe_reserve (elms, elements->dim);
for (size_t i = 0; i < elements->dim; i++)
{
Expression *e = (*elements)[i];
if (e->type->isintegral())
{
tree value = build_integer_cst (e->toInteger(), e->type->toCtype());
CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
}
else if (e->type->isfloating())
{
tree value = build_float_cst (e->toReal(), e->type);
CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
}
else
gcc_unreachable();
}

// Build vector type.
int nunits = ((TypeSArray *) expr->type)->dim->toUInteger();
Type *telem = expr->type->nextOf();
tree vectype = build_vector_type (telem->toCtype(), nunits);

cst = build_vector_from_ctor (vectype, elms);
}
else
cst = build_integer_cst (expr->toInteger(), expr->type->toCtype());
gcc_unreachable();

len = native_encode_expr (cst, buffer, sizeof (buffer));
cst = native_interpret_expr (type->toCtype(), buffer, len);
// Encode CST to buffer.
int len = native_encode_expr (cst, buffer, sizeof (buffer));

e = gcc_cst_to_d_expr (cst);
gcc_assert (e != NULL);
if (tb->ty == Tsarray)
{
// Interpret value as a vector of the same size,
// then return the array literal.
int nunits = ((TypeSArray *) type)->dim->toUInteger();
Type *elem = type->nextOf();
tree vectype = build_vector_type (elem->toCtype(), nunits);

return e;
cst = native_interpret_expr (vectype, buffer, len);

Expression *e = gcc_cst_to_d_expr (cst);
gcc_assert (e != NULL && e->op == TOKvector);

return ((VectorExp *) e)->e1;
}
else
{
// Normal interpret cast.
cst = native_interpret_expr (type->toCtype(), buffer, len);

Expression *e = gcc_cst_to_d_expr (cst);
gcc_assert (e != NULL);

return e;
}
}

/* Used to help initialize the builtin-types.def table. When a type of
Expand Down Expand Up @@ -1686,34 +1763,34 @@ ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
}


/* Backend init. */
// Backend init.

void
d_backend_init (void)
{
init_global_binding_level ();
init_global_binding_level();

/* This allows the code in d-builtins2 to not have to worry about
converting (C signed char *) to (D char *) for string arguments of
built-in functions.
Parameters are (signed_char = false, short_double = false). */
// This allows the code in d-builtins.c to not have to worry about
// converting (C signed char *) to (D char *) for string arguments of
// built-in functions.
// Parameters are (signed_char = false, short_double = false).
build_common_tree_nodes (false, false);

d_init_builtins ();
d_init_builtins();

if (flag_exceptions)
d_init_exceptions ();
d_init_exceptions();

/* This is the C main, not the D main. */
// This is the C main, not the D main.
main_identifier_node = get_identifier ("main");
}


/* Backend term. */
// Backend term.

void
d_backend_term (void)
{
}


#include "gt-d-d-builtins.h"
30 changes: 14 additions & 16 deletions gcc/d/d-codegen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,10 @@ d_convert (tree type, tree exp)
return error_mark_node;

Type *totype = build_dtype (type);
Type *expr_type = build_dtype (TREE_TYPE (exp));
Type *etype = build_dtype (TREE_TYPE (exp));

if (totype && expr_type)
return convert_expr (exp, expr_type, totype);
if (totype && etype)
return convert_expr (exp, etype, totype);

return convert (type, exp);
}
Expand Down Expand Up @@ -949,12 +949,10 @@ build_float_cst (const real_t& value, Type *totype)
tree type_node = tb->toCtype();
real_convert (&new_value.rv(), TYPE_MODE (type_node), &value.rv());

// Value grew as a result of the conversion. %% precision bug ??
// For now just revert back to original.
if (new_value > value)
{
// value grew as a result of the conversion. %% precision bug ??
// For now just revert back to original.
new_value = value;
}
new_value = value;

return build_real (type_node, new_value.rv());
}
Expand Down Expand Up @@ -1364,33 +1362,33 @@ tree
build_address (tree exp)
{
tree t, ptrtype;
tree exp_type = TREE_TYPE (exp);
tree type = TREE_TYPE (exp);
d_mark_addressable (exp);

// Gimplify doesn't like &(* (ptr-to-array-type)) with static arrays
if (TREE_CODE (exp) == INDIRECT_REF)
{
t = TREE_OPERAND (exp, 0);
ptrtype = build_pointer_type (exp_type);
ptrtype = build_pointer_type (type);
t = build_nop (ptrtype, t);
}
else
{
/* Just convert string literals (char[]) to C-style strings (char *), otherwise
the latter method (char[]*) causes conversion problems during gimplification. */
if (TREE_CODE (exp) == STRING_CST)
ptrtype = build_pointer_type (TREE_TYPE (exp_type));
ptrtype = build_pointer_type (TREE_TYPE (type));
/* Special case for va_list. The backends will be expecting a pointer to vatype,
* but some targets use an array. So fix it. */
else if (TYPE_MAIN_VARIANT (exp_type) == TYPE_MAIN_VARIANT (va_list_type_node))
else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node))
{
if (TREE_CODE (TYPE_MAIN_VARIANT (exp_type)) == ARRAY_TYPE)
ptrtype = build_pointer_type (TREE_TYPE (exp_type));
if (TREE_CODE (TYPE_MAIN_VARIANT (type)) == ARRAY_TYPE)
ptrtype = build_pointer_type (TREE_TYPE (type));
else
ptrtype = build_pointer_type (exp_type);
ptrtype = build_pointer_type (type);
}
else
ptrtype = build_pointer_type (exp_type);
ptrtype = build_pointer_type (type);

t = build1 (ADDR_EXPR, ptrtype, exp);
}
Expand Down
2 changes: 1 addition & 1 deletion gcc/d/d-codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ extern tree d_array_convert (Expression *exp);

// Simple constants
extern tree build_integer_cst (dinteger_t value, tree type = integer_type_node);
extern tree build_float_cst (const real_t& value, Type *target_type);
extern tree build_float_cst (const real_t& value, Type *totype);

extern dinteger_t cst_to_hwi (double_int cst);
extern dinteger_t tree_to_hwi (tree t);
Expand Down

0 comments on commit 262a5bd

Please sign in to comment.