/*
* 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/idl_id.h>
#include <mom/compiler.h>
#include <mom/libmint.h>
#include <mom/c/libcast.h>
#include <mom/c/libpres_c.h>
#include "mach3.h"
struct ool_check_functor : public functor
{
virtual void func(mu_state *must);
ool_check_functor() {};
ool_check_functor(cast_expr cond_expr,
int e_size,
cast_expr arr_expr,
cast_type arr_ctype,
cast_type el_ctype,
mint_ref el_itype,
pres_c_mapping el_map,
char *c_name) :
condition_expr(cond_expr),
elem_size(e_size),
array_expr(arr_expr),
array_ctype(arr_ctype),
elem_ctype(el_ctype),
elem_itype(el_itype),
elem_map(el_map),
cname(c_name)
{};
cast_expr condition_expr;
int elem_size;
cast_expr array_expr;
cast_type array_ctype;
cast_type elem_ctype;
mint_ref elem_itype;
pres_c_mapping elem_map;
char *cname;
};
struct ool_case_functor : public functor
{
virtual void func(mu_state *must);
ool_case_functor(cast_expr arr_expr,
cast_type arr_ctype,
cast_type el_ctype,
mint_ref el_itype,
pres_c_mapping el_map,
char *c_name) :
array_expr(arr_expr),
array_ctype(arr_ctype),
elem_ctype(el_ctype),
elem_itype(el_itype),
elem_map(el_map),
cname(c_name)
{};
cast_expr array_expr;
cast_type array_ctype;
cast_type elem_ctype;
mint_ref elem_itype;
pres_c_mapping elem_map;
char *cname;
};
struct inl_case_functor : public functor
{
virtual void func(mu_state *must);
inl_case_functor(cast_expr arr_expr,
cast_type arr_ctype,
cast_type el_ctype,
mint_ref el_itype,
pres_c_mapping el_map,
char *c_name) :
array_expr(arr_expr),
array_ctype(arr_ctype),
elem_ctype(el_ctype),
elem_itype(el_itype),
elem_map(el_map),
cname(c_name)
{};
cast_expr array_expr;
cast_type array_ctype;
cast_type elem_ctype;
mint_ref elem_itype;
pres_c_mapping elem_map;
char *cname;
};
void ool_check_functor::func(mu_state *must)
{
mu_memory_allocator_state *start_state;
cast_stmt saved_block, then_block, else_block;
struct mu_abort_block *mab_par, *mab_con, *mab_thr;
char *skip_label = must->add_label();
mu_msg_span *union_span = 0, *parent_span = 0;
must->break_chunk();
start_state = must->memory_allocator_state();
/*
* Set the servercopy flag, if we have one (the ``mustcopy'' argument).
*/
cast_expr scopy;
cast_type t;
int gotarg = must->arglist->getargs(cname, "mustcopy", &scopy, &t);
assert(gotarg);
if (scopy)
must->add_stmt(cast_new_stmt_expr(
cast_new_expr_assign(scopy,
cast_new_unary_expr(
CAST_UNARY_LNOT,
condition_expr))));
saved_block = must->c_block;
mab_par = must->abort_block;
mab_con = new mu_abort_block();
mab_con->set_kind(MABK_CONTROL_IF_ELSE);
mab_con->begin();
if( must->current_span ) {
union_span = new mu_msg_span;
union_span->set_kind(MSK_UNION);
union_span->set_block(must->c_block);
union_span->set_abort(must->abort_block);
union_span->begin();
parent_span = must->current_span;
must->current_span = new mu_msg_span;
must->current_span->set_kind(MSK_SEQUENTIAL);
must->current_span->begin();
}
mab_thr = new mu_abort_block();
must->abort_block = mab_thr;
mab_thr->set_kind(MABK_THREAD);
mab_thr->set_expr(condition_expr);
mab_thr->begin();
// Generate the out-of-line branch
must->c_block = cast_new_block(0, 0);
ool_case_functor ooln(array_expr, array_ctype,
elem_ctype, elem_itype, elem_map, cname);
must->mu_union_case(&ooln);
if (must->op & MUST_ENCODE) {
must->add_stmt(
cast_new_stmt_expr(cast_new_expr_op_assign(
CAST_BINARY_BOR,
cast_new_expr_name(
"_buf_start->Head.msgh_bits"),
cast_new_expr_name(
"MACH_MSGH_BITS_COMPLEX"))));
}
must->add_stmt(cast_new_goto(skip_label));
mab_thr->end();
mab_con->add_child(mab_thr, MABF_OUT_OF_LINE);
must->add_stmt(mab_thr->get_block_label());
if( parent_span ) {
must->current_span->end();
union_span->add_child(must->current_span);
must->current_span = new mu_msg_span;
must->current_span->set_kind(MSK_SEQUENTIAL);
must->current_span->begin();
}
mab_thr = new mu_abort_block();
must->abort_block = mab_thr;
mab_thr->set_kind(MABK_THREAD);
mab_thr->set_expr(0);
mab_thr->begin();
if( must->current_span ) {
must->current_span->end();
union_span->add_child(must->current_span);
must->current_span = new mu_msg_span;
must->current_span->set_kind(MSK_SEQUENTIAL);
must->current_span->begin();
}
then_block = must->c_block;
// Generate the in-line branch
must->set_memory_allocator_state(start_state);
must->c_block = cast_new_block(0, 0);
inl_case_functor inln(array_expr, array_ctype,
elem_ctype, elem_itype, elem_map, cname);
must->mu_union_case(&inln);
must->add_stmt(cast_new_goto(skip_label));
mab_thr->end();
mab_con->add_child(mab_thr, MABF_OUT_OF_LINE);
must->add_stmt(mab_thr->get_block_label());
if( parent_span ) {
must->current_span->end();
union_span->add_child(must->current_span);
union_span->end();
parent_span->add_child(union_span);
must->current_span = parent_span;
}
must->abort_block = mab_par;
mab_con->end();
mab_par->add_child(mab_con, MABF_OUT_OF_LINE);
mab_par->add_stmt(mab_con->get_block_label());
else_block = must->c_block;
// Now make the if statement
must->c_block = saved_block;
must->add_stmt(cast_new_if(condition_expr,
then_block,
else_block));
cast_stmt clabel
= cast_new_label(skip_label, cast_new_stmt(CAST_STMT_EMPTY));
clabel->cast_stmt_u_u.s_label.users = 2;
must->add_stmt(clabel);
}
void ool_case_functor::func(mu_state *must)
{
/*
* First, we have to ``fix'' the allocation semantics for this case.
* Out-of-line data is never allocated since the MACH kernel will do
* that for us. To do this, we replace the allocation semantics in the
* associated allocation context with a tweaked one.
*/
mu_inline_alloc_context *iac = must->inline_alloc_context;
while (iac) {
if (strcmp(iac->name, cname) == 0)
break;
iac = iac->parent_context;
}
if (!iac)
panic(("In `ool_case_functor::func', "
"allocation context `%s' not available."), cname);
pres_c_allocation *orig_alloc = iac->alloc;
pres_c_allocation aalloc = *orig_alloc;
iac->alloc = &aalloc;
/*
* Create a new allocation semantic for sending the data out-of-line.
* (The default allocation semantic assumes inline transmission.)
*
* XXX - This is a terrible hack, since the PG should be able
* to express the proper allocation semantic using the
* pres_c_allocation structure (including necessary runtime
* checks). Until we have a new allocation representation,
* however, we have to munge the allocation here to force
* proper allocation.
*/
for (int i = 1; i < PRES_C_DIRECTIONS; i++) {
/* Skip "invalid" allocation cases. */
if (aalloc.cases[i].allow != PRES_C_ALLOCATION_ALLOW)
continue;
aalloc.cases[i].pres_c_allocation_u_u.val.allocator.kind
= PRES_C_ALLOCATOR_OUTOFLINE;
/*
* Never alloc out-of-line pointers; we might dealloc, though.
*
* XXX - We mark this to never be deallocated, but that is
* wrong if the work function isn't aware that this data came
* out-of-line (the reason we're in this functor is because it
* may be ``optimized'' at runtime to go out-of-line if the
* array is large). The `servercopy' parameter, if it exists,
* informs the work function of this fact, and thus passes it
* the responsibility for deallocation. However, if there is
* no `servercopy' parameter, we have to treat it like the rest
* of the `in' data and free it. Unfortunatlely, we need to
* *EXPLICITLY* free it (the other `in' data is stack-allocated
* and automatically freed).
*/
aalloc.cases[i].pres_c_allocation_u_u.val.flags
&= ~PRES_C_ALLOC_EVER;
aalloc.cases[i].pres_c_allocation_u_u.val.allocator.
pres_c_allocator_u.ool_name = ir_strlit("mach_vm");
}
/*
* We set our magic Out-of-line data flag, and marshal the data.
*/
((mach3_mu_state *)must)->mach3_outofline = 1;
must->mu_array(array_expr, array_ctype,
elem_ctype, elem_itype, elem_map, cname);
((mach3_mu_state *)must)->mach3_outofline = 0;
/* Restore the original allocation semantics. */
iac->alloc = orig_alloc;
}
void inl_case_functor::func(mu_state *must)
{
/* The inline case is just the normal thing. */
must->mu_array(array_expr, array_ctype,
elem_ctype, elem_itype, elem_map, cname);
}
void mach3_mu_state::mu_array_type_descriptor(
cast_expr len_expr, int fixed_elts,
char *prim_macro_name, int longform, int out_of_line,
cast_expr dealloc_expr, cast_expr port_type, cast_expr oolcheck)
{
/* Produce a macro invocation to marshal the type descriptor. */
char *macro_name = flick_asprintf("%s_type", prim_macro_name);
cast_expr macro_expr = cast_new_expr_name(macro_name);
cast_expr ofs_expr = cast_new_expr_lit_int(
chunk_prim(2, longform ? 12 : 4), 0);
cast_expr num_expr;
if (fixed_elts > 1) {
num_expr = cast_new_binary_expr(
CAST_BINARY_MUL,
len_expr,
cast_new_expr_lit_int(fixed_elts, 0));
} else
num_expr = len_expr;
if (op & MUST_DECODE) {
if (len_expr->kind == CAST_EXPR_LIT_PRIM) {
/*
* if we are decoding an array, the length MUST be in
* a variable in order to decode the type!
*/
cast_expr lexpr =
add_temp_var(
"array_length",
cast_new_prim_type(
CAST_PRIM_INT,
CAST_MOD_UNSIGNED));
add_stmt(cast_new_stmt_expr(
cast_new_expr_assign(lexpr, num_expr)));
num_expr = lexpr;
} else if (num_expr != len_expr) {
add_stmt(cast_new_stmt_expr(
cast_new_expr_assign(len_expr, num_expr)));
num_expr = len_expr;
}
}
cast_expr inl_expr;
if (oolcheck)
inl_expr = cast_new_unary_expr(CAST_UNARY_LNOT,
oolcheck);
else
inl_expr = cast_new_expr_lit_int(!out_of_line, 0);
cast_expr long_expr = cast_new_expr_name(
longform ? "_long_type" : "_type");
cast_expr cex;
/* For ports, we need to add an extra param to the macro call
-- the port type */
if (port_type) {
cex = cast_new_expr_call(macro_expr, 6);
cast_set_expr_array(
&cex->cast_expr_u_u.call.params,
ofs_expr,
port_type,
num_expr,
inl_expr,
dealloc_expr,
long_expr,
NULL);
is_complex = (cast_expr) 1;
} else {
cex = cast_new_expr_call_5(macro_expr,
ofs_expr,
num_expr,
inl_expr,
dealloc_expr,
long_expr);
}
add_stmt(cast_new_stmt_expr(cex));
}
void mach3_mu_state::mu_aggregated_array(
cast_expr array_expr, cast_type array_ctype,
pres_c_allocation *array_alloc,
cast_type elem_ctype, mint_ref elem_itype,
pres_c_mapping elem_map,
cast_expr len_expr, cast_type /*len_ctype*/,
unsigned long /*len_min*/, unsigned long len_max,
mint_ref prim_itype, int fixed_elts,
int out_of_line, char *cname)
{
mach3_array = 1;
assert(prim_itype >= 0);
assert(prim_itype < (mint_ref) pres->mint.defs.defs_len);
mint_def *pidef = &pres->mint.defs.defs_val[prim_itype];
/* Decide whether to use a shortform or longform type descriptor. */
int longform = (len_max >= 4096);
/* Find the vital parameters of the primitive array elements. */
int prim_size = -1, prim_align_bits = -1;
char *prim_macro_name = 0;
if (pidef->kind != MINT_VOID) {
get_prim_params(prim_itype, &prim_size, &prim_align_bits,
&prim_macro_name);
if (!prim_macro_name) {
panic(("In `mach3_mu_state::mu_aggregated_array', "
"invalid MINT type (%d) encountered."),
prim_itype);
}
}
/* See if we have a servercopy argument available. */
cast_expr scopy;
cast_type scopyt;
int gotarg = arglist->getargs(cname, "mustcopy", &scopy, &scopyt);
assert(gotarg);
/*
* We need a runtime out-of-line check for unbounded `inline' arrays.
* But we don't need it if we are just deallocating the array and have
* a servercopy argument (since the work function is then responsible
* for deallocation, and we don't have to do a thing).
*/
cast_expr oolcheck = 0;
if (len_max == 0xffffffff /* unbounded array */
&& !out_of_line
&& !((op & MUST_DEALLOCATE) && pidef->kind == MINT_VOID
&& scopy)) {
/* send inline if <= 2K, OOL if > 2K */
oolcheck = add_temp_var(
"ool_check",
cast_new_prim_type(CAST_PRIM_INT, 0));
}
cast_expr limit2m;
if (prim_size > 0) {
limit2m = cast_new_expr_lit_int(
2048 / (prim_size * fixed_elts),
0);
} else {
limit2m =
cast_new_binary_expr(CAST_BINARY_DIV,
cast_new_expr_lit_int(2048, 0),
cast_new_expr_sizeof_type(
elem_ctype));
}
if (oolcheck && (op & MUST_ENCODE)) {
add_stmt(
cast_new_stmt_expr(
cast_new_expr_assign(
oolcheck,
cast_new_binary_expr(
CAST_BINARY_GT,
len_expr,
limit2m))));
}
/* Output the proper tag for strings (esp. fixed-length strings). */
if (mu_array_is_string(cname)) {
prim_macro_name = flick_asprintf("flick_%s_%s_string_c",
get_be_name(),
get_buf_name());
}
if (pidef->kind != MINT_VOID) {
/* Find/make the deallocation expression. */
cast_expr dealloc_expr = 0;
cast_type t;
int dealloc_always = ((get_allocator_flags(array_alloc)
& PRES_C_DEALLOC_EVER)
== PRES_C_DEALLOC_ALWAYS);
if (dealloc_always) {
gotarg = arglist->getargs(cname, "release",
&dealloc_expr, &t);
assert(gotarg);
}
if (!dealloc_expr)
dealloc_expr
= cast_new_expr_lit_int(
(out_of_line && dealloc_always), 0);
/* For ports, we need to add an extra param to the macro call
-- the port type */
cast_expr port_type = 0;
if (pres->mint.defs.defs_val[prim_itype].kind
== MINT_INTERFACE) {
pres_c_mapping temp_map;
/*
* XXX -- Dig through any stub that may be in the way.
*/
if (elem_map->kind == PRES_C_MAPPING_STUB) {
int stub_num = pres_c_find_mu_stub(
pres, elem_itype, elem_ctype,
elem_map, PRES_C_MARSHAL_STUB);
temp_map = pres->stubs.stubs_val[stub_num].
pres_c_stub_u.mstub.seethru_map;
} else
temp_map = elem_map;
assert(temp_map->kind == PRES_C_MAPPING_REFERENCE);
port_type = cast_new_expr_name(
get_mach_port_type(
&temp_map->pres_c_mapping_u_u.ref,
prim_itype));
is_complex = (cast_expr) 1;
}
mu_array_type_descriptor(len_expr, fixed_elts,
prim_macro_name, longform,
out_of_line, dealloc_expr,
port_type, oolcheck);
}
/* Now descend into the array and marshal the individual elements. */
if (oolcheck && (op & MUST_DECODE)) {
add_stmt(
cast_new_stmt_expr(
cast_new_expr_assign(
oolcheck,
cast_new_binary_expr(
CAST_BINARY_GT,
len_expr,
limit2m))));
}
if (oolcheck && pidef->kind != MINT_VOID) {
/*
* Add a check to see if this should go inline or out-of-line.
*/
ool_check_functor ocf(oolcheck, prim_size * fixed_elts,
array_expr, array_ctype, elem_ctype,
elem_itype, elem_map, cname);
mu_union(&ocf);
if (is_complex != (void *) 1) {
is_complex = oolcheck;
}
last_ool_check = oolcheck;
} else if (oolcheck && pidef->kind == MINT_VOID) {
/*
* Add a check to see if we need to deallocate this out-of-line
* `in' data. (It may have been sent out-of-line, so we must
* preserve the ``in-line'' semantics of the parameter in that
* it is destroyed after the server work function has finished.
* This happens automatically for in-line data by recycling the
* message buffer, but out-of-line data normally isn't freed.)
* If a servercopy argument exists, then we don't have to worry
* about it, since the responsibility for deallocation then
* rests on the work function.
*/
/* set up a new c_block to capture the deallocation. */
cast_stmt orig_cblock = c_block;
c_block = 0;
/*
* Create a new allocation semantic for deallocating the data.
* (The default allocation semantic assumes inline
* transmission, and thus no deallocation.)
*
* XXX - This is a terrible hack, since the PG should be able
* to express the proper allocation semantic using the
* pres_c_allocation structure (including necessary runtime
* checks). Until we have a new allocation representation,
* however, we have to munge the allocation here to force
* proper allocation.
*/
pres_c_allocation aalloc;
for (int i = 0; i < PRES_C_DIRECTIONS; i++) {
/* The `in' direction is the only valid one here. */
if (i != PRES_C_DIRECTION_IN) {
aalloc.cases[i].allow
= PRES_C_ALLOCATION_INVALID;
continue;
}
aalloc.cases[i].allow = PRES_C_ALLOCATION_ALLOW;
/*
* The allocator must be a PRES_C_ALLOCATOR_NAME
* since PRES_C_ALLOCATOR_OUTOFLINE assumes the
* deallocation is taken care of by the kernel.
*/
aalloc.cases[i].pres_c_allocation_u_u.val.allocator.
kind = PRES_C_ALLOCATOR_NAME;
aalloc.cases[i].pres_c_allocation_u_u.val.allocator.
pres_c_allocator_u.name = ir_strlit("mach_vm");
aalloc.cases[i].pres_c_allocation_u_u.val.flags
= PRES_C_DEALLOC_ALWAYS;
}
pres_c_allocation old_alloc = *array_alloc;
*array_alloc = aalloc;
mem_mu_state::mu_array(array_expr, array_ctype, elem_ctype,
elem_itype, elem_map, cname);
*array_alloc = old_alloc;
cast_stmt dealloc_if
= cast_new_if(oolcheck, c_block, 0);
/* Restore the c_block and add the dealloc `if'. */
c_block = orig_cblock;
add_stmt(dealloc_if);
} else if (out_of_line && pidef->kind != MINT_VOID) {
/* Allocate space */
if ((op & MUST_ALLOCATE) &&
(array_ctype->kind == CAST_TYPE_POINTER))
mu_pointer_alloc(array_expr, elem_ctype, cname);
/*
* 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);
/*
* Here we m/u the pointer itself, literally, into the
* standard data stream (as an unsigned32 value). The Mach
* kernel handles the rest.
*/
mu_mapping_simple(array_expr,
cast_new_prim_type(CAST_PRIM_INT,
CAST_MOD_UNSIGNED),
pres->mint.standard_refs.unsigned32_ref);
/*
* 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);
/* Deallocate space */
if ((op & MUST_DEALLOCATE) &&
(array_ctype->kind == CAST_TYPE_POINTER))
mu_pointer_free(array_expr, elem_ctype, cname);
} else if (!((op & MUST_DEALLOCATE) && pidef->kind == MINT_VOID
&& scopy)) {
mem_mu_state::mu_array(array_expr, array_ctype, elem_ctype,
elem_itype, elem_map, cname);
}
mach3_array = 0;
/* we need to align ourselves to a 4-byte boundary */
if ((align_bits < 2) || (align_ofs & 3))
chunk_prim(2, 0);
}
void mach3_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)
{
/* Decide whether to transmit it in-line or out-of-line. */
mu_inline_alloc_context *iac = inline_alloc_context;
while (iac) {
if (strcmp(iac->name, cname) == 0)
break;
iac = iac->parent_context;
}
assert(iac);
int out_of_line = 0;
if (get_allocator_kind(iac->alloc).kind == PRES_C_ALLOCATOR_OUTOFLINE
|| mach3_outofline) {
out_of_line = 1;
/*
* If `mach3_outofline' is set, then we're forcing data
* out-of-line because it's > 2K. The `is_complex' flag
* should only be set here if we have data ALWAYS sent
* out-of-line (rather than conditionally).
*/
if (!mach3_outofline) {
is_complex = (cast_expr) 1;
}
}
/* Now make sure we have a valid length expression in the arglist. */
cast_expr len_expr;
cast_type len_ctype;
int gotarg = arglist->getargs(cname, "length", &len_expr, &len_ctype);
assert(gotarg);
assert(len_expr);
assert(len_ctype);
/* See if the whole array can be lumped under one MIG type descriptor.
This is possible iff this is an array of [fixed arrays of...]
primitive types. At the same time, compute the total number of
primitive elements contained in each element of this (top-level,
possibly variable-length) array. */
mint_ref prim_itype = elem_itype;
int fixed_elts = 1;
unsigned len_min, len_max;
mu_array_get_encoded_bounds(&len_min, &len_max, cname);
if (out_of_line
|| (pres->mint.defs.defs_val[elem_itype].kind == MINT_VOID)
|| (array_data.is_valid && len_max > 1)) while (1) {
assert(prim_itype >= 0);
assert(prim_itype < (signed int)pres->mint.defs.defs_len);
mint_def *def = &pres->mint.defs.defs_val[prim_itype];
/*
* Don't try to aggregate again if we're already aggregating.
*/
if (mach3_array)
break;
if ((def->kind == MINT_INTEGER) ||
(def->kind == MINT_FLOAT) ||
(def->kind == MINT_CHAR) ||
(def->kind == MINT_VOID) ||
(def->kind == MINT_INTERFACE)) {
/* We reached the primitive type at the bottom,
so aggregation is possible - do it. */
mu_aggregated_array(array_expr, array_ctype,
iac->alloc,
elem_ctype, elem_itype, elem_map,
len_expr, len_ctype,
len_min, len_max,
prim_itype, fixed_elts,
out_of_line, cname);
return;
} else if (def->kind == MINT_ARRAY) {
unsigned array_min, array_max;
mint_get_array_len(&pres->mint, prim_itype,
&array_min, &array_max);
if (array_min != array_max) {
/* Can't aggregate arrays of variable-length
arrays.*/
break;
}
fixed_elts *= array_min;
/* simple overflow check */
assert(fixed_elts % array_min == 0);
prim_itype = def->mint_def_u.array_def.element_type;
} else {
/* Saw something else - no aggregation possible.
*
* XXX - presentations other than MIG may cause this
* case to occur, so we can't panic here... But for
* MIG arrays, we have to know what type to send for
* the type tag. If we get here, we don't know, and
* thus can't make a correct tag. It would be wrong
* to handle it "the normal way", because no tag would
* be associated with this array, and the message
* would not be correctly interpreted by the kernel.
*/
#if 0
panic("Can't determine type of array data!");
#else
static int is_warned = 0;
if (!is_warned++)
warn("Can't determine type of array data!");
#endif
break;
}
}
/* No aggregation possible - deal with the array the normal way. */
if (out_of_line
&& pres->mint.defs.defs_val[prim_itype].kind != MINT_VOID) {
/* Allocate space */
if ((op & MUST_ALLOCATE) &&
(array_ctype->kind == CAST_TYPE_POINTER))
mu_pointer_alloc(array_expr, elem_ctype, cname);
/*
* Here we m/u the pointer itself, literally, into the
* standard data stream (as an unsigned32 value). The Mach
* kernel handles the rest.
*/
mu_mapping_simple(array_expr,
cast_new_prim_type(CAST_PRIM_INT,
CAST_MOD_UNSIGNED),
pres->mint.standard_refs.unsigned32_ref);
/* Deallocate space */
if ((op & MUST_DEALLOCATE) &&
(array_ctype->kind == CAST_TYPE_POINTER))
mu_pointer_free(array_expr, elem_ctype, cname);
} else {
mem_mu_state::mu_array(array_expr, array_ctype, elem_ctype,
elem_itype, elem_map, cname);
}
}
/*
* For Mach3MIG strings, we encode the terminator as part of the string.
*/
int mach3_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