/*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
*
* This file is part of Flick, the Flexible IDL Compiler Kit.
*
* Flick is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Flick is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Flick; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place #330, Boston, MA 02111, USA.
*/
#include <assert.h>
#include <mom/compiler.h>
#include <mom/libmint.h>
#include <mom/c/libcast.h>
#include <mom/c/pbe.hh>
struct xlate_inline_state : public inline_state
{
inline_state *orig;
int changed_slot;
cast_expr new_expr;
cast_type new_type;
virtual void slot_access(int slot,
cast_expr *out_expr, cast_type *out_type);
};
void xlate_inline_state::slot_access(int slot,
cast_expr *out_expr, cast_type *out_type)
{
if (slot == changed_slot) {
*out_expr = new_expr;
*out_type = new_type;
} else
orig->slot_access(slot, out_expr, out_type);
}
void mu_state::mu_inline_xlate(inline_state *ist,
mint_ref itype, pres_c_inline inl)
{
pres_c_inline_xlate *xinl = &(inl->pres_c_inline_u_u.xlate);
assert(xinl->sub);
assert(xinl->internal_ctype);
assert(xinl->translator);
/*
* The `&' and `~' translator strings are special translators used to
* signal that a fixed array or fixed struct translation is needed.
* Used by the MIG FE/PG.
*/
assert((xinl->translator[0] == 0)
|| (xinl->translator[0] == '&')
|| (xinl->translator[0] == '~')
);
/* Find the external type and expression. */
cast_expr external_expr;
cast_type external_type;
cast_type int_ctype;
ist->slot_access(xinl->index, &external_expr, &external_type);
/*
* Create a new inline_state that represents the original one, but with
* the appropriate slot's ctype replaced with the internal type.
*/
xlate_inline_state xist;
xist.orig = ist;
xist.changed_slot = xinl->index;
cast_expr internal_var_expr = 0;
if ((xinl->translator[0] == '&') || (xinl->translator[0] == '~')) {
int_ctype = xinl->internal_ctype;
/*
* change any CAST_TYPE_ARRAY's to CAST_TYPE_POINTER's so
* we don't allocate space, when all we want is a
* pointer.
*/
if ((int_ctype->kind == CAST_TYPE_POINTER) &&
(int_ctype->cast_type_u_u.pointer_type.target->kind
== CAST_TYPE_ARRAY))
int_ctype
= cast_new_pointer_type(
cast_new_pointer_type(
int_ctype->cast_type_u_u.
pointer_type.target->
cast_type_u_u.array_type.
element_type));
else if (int_ctype->kind == CAST_TYPE_ARRAY)
int_ctype
= cast_new_pointer_type(
int_ctype->cast_type_u_u.array_type.
element_type);
/*
* Create a temporary variable of the internal type, to
* marshal into or out of.
*/
internal_var_expr = add_temp_var("internal", int_ctype);
xist.new_type = int_ctype;
xist.new_expr = internal_var_expr;
} else { /* ECP These should be at least structurally equivalent */
/* assert(!cast_cmp_type(external_type, xinl->internal_ctype)); */
xist.new_type = int_ctype = external_type;
xist.new_expr = external_expr;
}
if (xinl->translator[0] == '&') {
/*
* The `&' translator signals that the address of the object
* should be cast into the internal C type.
*/
add_stmt(cast_new_stmt_expr(
cast_new_expr_assign(
internal_var_expr,
cast_new_expr_cast(
cast_new_unary_expr(CAST_UNARY_ADDR,
external_expr),
int_ctype
))));
mu_inline(&xist, itype, xinl->sub);
#if 0
/*
* The `memcpy' that was previously output below is entirely unnecessary. We
* already encoded or decoded to the target of the internal variable pointer.
*/
mint_def *def = &pres->mint.mint_1_val[itype];
assert(def->kind == MINT_ARRAY);
mint_array_def *adef = &def->mint_def_u.array_def;
mint_ref length_itype = adef->length_type;
mint_def *length_def = &pres->mint.mint_1_val[length_itype];
assert(length_def->kind == MINT_INTEGER);
int array_len = (length_def->mint_def_u.integer_def.range ?
length_def->mint_def_u.integer_def.range :
length_def->mint_def_u.integer_def.min);
/* XXX --- Will this work? */
add_stmt(cast_new_stmt_expr(
cast_new_expr_call_3(
cast_new_expr_name("memcpy"),
cast_new_expr_cast(
cast_new_unary_expr(CAST_UNARY_ADDR,
external_expr),
cast_new_pointer_type(
cast_new_type(CAST_TYPE_VOID))
),
cast_new_expr_cast(
internal_var_expr,
cast_new_pointer_type(
cast_new_type(CAST_TYPE_VOID))
),
cast_new_expr_lit_int(array_len, 0)
)));
#endif
#if 0
add_stmt(cast_new_stmt_expr(
cast_new_expr_assign(
external_expr,
cast_new_expr_cast(cast_new_unary_expr(
CAST_UNARY_DEREF,internal_var_expr),
external_type))));
#endif
} else if (xinl->translator[0] == '~') {
/*
* The `~' translator signals that we are dealing with a fixed
* size array.
*/
add_stmt(cast_new_stmt_expr(
cast_new_expr_assign(
internal_var_expr,
cast_new_expr_cast(external_expr, int_ctype)
)));
mu_inline(&xist, itype, xinl->sub);
#if 0
/*
* The `memcpy' that was previously output below is entirely unnecessary. We
* already encoded or decoded to the target of the internal variable pointer.
*/
mint_def *def = &pres->mint.mint_1_val[itype];
int array_len;
if (def->kind == MINT_ARRAY) {
mint_array_def *adef = &(def->mint_def_u.array_def);
mint_ref length_itype = adef->length_type;
mint_def *length_def
= &(pres->mint.mint_1_val[length_itype]);
assert(length_def->kind == MINT_INTEGER);
array_len = (length_def->mint_def_u.integer_def.range ?
length_def->mint_def_u.integer_def.range :
length_def->mint_def_u.integer_def.min);
} else {
array_len = (def->mint_def_u.integer_def.range ?
def->mint_def_u.integer_def.range :
def->mint_def_u.integer_def.min);
}
/* XXX Will this work? */
add_stmt(cast_new_stmt_expr(
cast_new_expr_call_3(
cast_new_expr_name("memcpy"),
cast_new_expr_cast(
external_expr,
cast_new_pointer_type(
cast_new_type(CAST_TYPE_VOID))
),
cast_new_expr_cast(
internal_var_expr,
cast_new_pointer_type(
cast_new_type(CAST_TYPE_VOID))
),
cast_new_expr_lit_int(array_len, 0)
)));
#endif
} else {
/*
* We have a simple cast between the presented C type and the
* C internal type.
*/
#if 0
if ((op & MUST_ENCODE)
&& (int_ctype->kind == CAST_TYPE_POINTER)
)
/*
* We are going to encode from the internal var, or we
* are going to decode to the address pointed to by our
* internal var.
*/
add_stmt(cast_new_stmt_expr(
cast_new_expr_assign(
internal_var_expr,
cast_new_expr_cast(
external_expr,
int_ctype
))));
#endif
mu_inline(&xist, itype, xinl->sub);
#if 0
if (op & MUST_DECODE)
/*
* We decoded into the internal var itself, and not
* into the address pointed at by our internal var.
*/
add_stmt(cast_new_stmt_expr(
cast_new_expr_assign(
external_expr,
cast_new_expr_cast(
internal_var_expr,
external_type
))));
#endif
}
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1