/*
* Copyright (c) 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/libpres_c.h>
#include "trapeze.h"
static void check_for_warning(unsigned len_max, cast_expr has_payload, cast_expr ptr)
{
static int spitwarn1 = 0;
static int spitwarn2 = 0;
if (!spitwarn1
&& len_max > TRAPEZE_MAX_PAYLOAD_SIZE) {
warn("Maximum size of arrays cannot exceed %d bytes.",
TRAPEZE_MAX_PAYLOAD_SIZE);
spitwarn1++;
}
if (!spitwarn2
&& has_payload
&& has_payload != ptr) {
warn("Only one array can be sent in a message!");
spitwarn2++;
}
}
void trapeze_mu_state::mu_array(cast_expr array_expr,
cast_type array_ctype,
cast_type elem_ctype,
mint_ref elem_itype,
pres_c_mapping elem_map,
char *cname)
{
int elem_size, elem_align_bits;
/* see if a bcopy is possible for this data */
cast_expr bcopy_poss = mu_get_sizeof(elem_itype,
elem_ctype,
elem_map,
&elem_size,
&elem_align_bits);
/* If the array is small, let's just put it in the control buffer. */
unsigned len_min, len_max, control_msg_data_size;
mu_array_get_encoded_bounds(&len_min, &len_max, cname);
control_msg_data_size = get_control_msg_data_size();
if ((len_max <= 1)
|| (bcopy_poss
&& ((len_max < control_msg_data_size) /* XXX check overflow */
&& (len_max * elem_size + max_msg_size
< control_msg_data_size)))) {
/* Do the normal thing and bail. */
mem_mu_state::mu_array(array_expr, array_ctype,
elem_ctype, elem_itype, elem_map,
cname);
return;
}
/* allocate a DMA buffer, if needed
(but not for the special environment var _ev) */
if ((op & MUST_ALLOCATE) &&
(array_ctype->kind == CAST_TYPE_POINTER) &&
(elem_itype == pres->mint.standard_refs.void_ref) &&
array_expr->kind == CAST_EXPR_NAME &&
strcmp(array_expr->cast_expr_u_u.name.
cast_scoped_name_val[0].name, "_ev")) {
add_stmt(cast_new_stmt_expr(cast_new_expr_assign(
array_expr, cast_new_expr_name(
flick_asprintf("flick_%s_%s_array__alloc()",
get_be_name(),
which_stub,
get_buf_name())))));
return;
}
/* Get the length expression from the arglist. */
cast_expr len_expr;
cast_type len_type;
int gotarg = arglist->getargs(cname, "length", &len_expr, &len_type);
assert(gotarg);
assert(len_expr);
assert(len_type);
/* calculate the length in bytes of the array */
if (!bcopy_poss)
bcopy_poss = cast_new_expr_sizeof_type(elem_ctype);
cast_expr length_expr =
cast_new_binary_expr(CAST_BINARY_MUL,
bcopy_poss,
len_expr);
/*
* Bounds check the array, but only for *real* arrays.
* Normally, this is taken care of by the standard mu_array(), but
* we aren't running that here.
*/
if (array_data.is_valid)
mu_array_check_bounds(cname);
/* Check for bit translation */
cast_stmt bt_if = mu_bit_translation_necessary(0, elem_itype);
assert(bt_if);
cast_stmt bt_end = mu_bit_translation_necessary(2, elem_itype);
assert(bt_end);
if (strncmp("#if 0", bt_if->cast_stmt_u_u.text, 5) == 0) {
bt_if = bt_end = 0;
}
/* swap on encode */
if (bt_if && (op & MUST_ENCODE)
&& (elem_size == 8 || elem_size == 4 || elem_size == 2)) {
add_stmt(bt_if);
add_stmt(cast_new_stmt_expr(cast_new_expr_call_2(
cast_new_expr_name(flick_asprintf(
"flick_%s_array_swap%d",
get_be_name(),
elem_size * 8)),
array_expr,
length_expr)));
add_stmt(bt_end);
}
/* call the macro to do the [un]marshaling */
cast_expr macro = cast_new_expr_name(
flick_asprintf("flick_%s_%s_%s_array",
get_be_name(),
which_stub,
get_buf_name()));
cast_expr call = cast_new_expr_call_2(macro,
array_expr,
length_expr);
add_stmt(cast_new_stmt_expr(call));
/* swap on decode */
if (bt_if && (op & MUST_DECODE)
&& (elem_size == 8 || elem_size == 4 || elem_size == 2)) {
add_stmt(bt_if);
add_stmt(cast_new_stmt_expr(cast_new_expr_call_2(
cast_new_expr_name(flick_asprintf(
"flick_%s_array_swap%d",
get_be_name(),
elem_size * 8)),
array_expr,
length_expr)));
add_stmt(bt_end);
}
/*
* Terminate the array, but only for *real* arrays.
* Normally, this is taken care of by the standard mu_array(), but
* we aren't running that here.
*/
if (array_data.is_valid)
mu_array_terminate(array_expr, elem_ctype, cname);
/* check the size of the array */
check_for_warning(array_data.mint_len_max, has_payload, array_expr);
if (!has_payload)
has_payload = array_expr;
/* Can't dealloc until message is sent */
}
/*
* For Trapeze strings, we encode the terminator as part of the string.
*/
int trapeze_mu_state::mu_array_encode_terminator(char *cname)
{
return mu_array_is_string(cname);
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1