Example #1
0
// Generate function epilog
void gfunc_epilog(void) {
  // Mark end of code
  gbranch(CodeEnd);
  
  // Output code for function
  gcode();

  // Clear code buffer
  clear_code_buf();
}
Example #2
0
void po_get_function(Poco_cb *pcb, Exp_frame *e)
/*****************************************************************************
 * entry point from statement parsing.	find function, then code the call.
 *	upon entry, we've seen the opening paren of the function call, and
 *	the expression frame (e) already holds the code to access the symbol
 *	which is the name of the function.
 *
 * if we have a pointer to a function, that wasn't explicitly dereferenced,
 * we code the dereference part first, and adjust the expression type.
 * (allows function calls as either "(*ptr)()" or "ptr()".  in the former
 * case, the deref has already been coded, we handle the latter case here.)
 *
 ****************************************************************************/
{
Type_info	*ti = &e->ctc;
int 		end_type = ti->comp[ti->comp_count-1];
Func_frame	*fuf;


	if (end_type == TYPE_POINTER &&
		ti->comp_count > 2 &&
		ti->comp[ti->comp_count-2] == TYPE_FUNCTION)
		{
		e->ctc.comp_count -= 1;
		end_type = ti->comp[ti->comp_count-1];
		po_set_ido_type(&e->ctc);
		po_make_deref(pcb,e);
		}

	if (end_type != TYPE_FUNCTION)
		{
		po_say_fatal(pcb, "trying to call something that's not a function");
		return;
		}

	fuf = ti->sdims[ti->comp_count-1].pt;

	e->ctc.comp_count -= 1;
	po_set_ido_type(&e->ctc);
	end_type = ti->comp[ti->comp_count-1];

	mk_function_call(pcb, e, fuf, end_type);

	clear_code_buf(pcb, &e->left);	/* if we had code in the left side, nuke  */
	e->left_complex = FALSE;		/* it, we've now processed it into a call.*/

	if (end_type == TYPE_POINTER)			/* if function returns a pointer  */
		{									/* put a NOP into the left buffer,*/
		po_code_op(pcb, &e->left, OP_NOP);	/* to signal we do have an lval.  */
		}									/* if it gets deref'd the NOP gets*/
}											/* replaced by the call code later*/
Example #3
0
static void mk_function_call(Poco_cb *pcb, Exp_frame *e,
	Func_frame *fff, SHORT ftype)
/*****************************************************************************
 * generate code to push parms to stack and make call to function.
 ****************************************************************************/
{
Symbol		*param;
SHORT		expected_count;
SHORT		idot;
SHORT		param_count = 0;
int 		param_size = 0;
SHORT		varg_param_count = 0;
int 		varg_param_size = 0;
int 		this_param_size;
Boolean 	is_cvarg_call = FALSE;
Exp_frame	*param_exps = NULL;
Exp_frame	*exp;
Code_buf	callcode;

po_init_code_buf(pcb, &callcode);
param = fff->parameters;
expected_count = fff->pcount;
for (;;)
	{
	if (param == NULL)
		break;
	if (po_is_next_token(pcb, TOK_RPAREN))
		break;

	exp = po_new_expframe(pcb);
	exp->next = param_exps;
	param_exps = exp;
	po_get_expression(pcb, exp);

	if (param->flags & SFL_ELLIP)
		{
		if (fff->type == CFF_C)
			{ /* ptr parms passed to c functions get un-poco-pointerized */
			if (po_is_pointer(&exp->ctc) || po_is_array(&exp->ctc))
				{
				po_code_op(pcb, &exp->ecd, OP_PPT_TO_CPT);
				exp->ctc.comp[exp->ctc.comp_count-1] = TYPE_CPT;
				exp->ctc.ido_type = IDO_CPT;
				}
#ifdef STRING_EXPERIMENT
			else if (po_is_string(&exp->ctc))
				{
				po_code_op(pcb, &exp->ecd, OP_STRING_TO_CPT);
				exp->ctc.comp[0] = TYPE_CHAR;
				exp->ctc.comp[1] = TYPE_CPT;
				exp->ctc.ido_type = IDO_CPT;
				}
#endif /* STRING_EXPERIMENT */
			this_param_size = po_get_param_size(pcb, exp->ctc.ido_type);
			varg_param_size += this_param_size;
			++varg_param_count;
			}
		}
	else
		{
		po_coerce_expression(pcb, exp, param->ti, FALSE);
		this_param_size = po_get_param_size(pcb, exp->ctc.ido_type);
		}

	++param_count;
	param_size += this_param_size;

	if (!(param->flags & SFL_ELLIP))
		param = param->link;

	po_need_token(pcb);

	if (param != NULL)
		{
		if (param->flags&SFL_ELLIP)
			{
			if (pcb->t.toktype != ',')
				{
				if ( pcb->t.toktype != ')')
					po_expecting_got(pcb, ", or )");
				else
					pushback_token(&pcb->t);
				}
			}
		else
			{
			if (pcb->t.toktype != ',')
				{
				if (pcb->t.toktype == ')')
					goto NOT_ENOUGH_PARMS;
				else
					po_expecting_got(pcb, ",");
				}
			}
		}
	else
		{
		pushback_token(&pcb->t);
		}
	}

if (param != NULL && (param->flags & SFL_ELLIP))
	{
	--expected_count;
	if (fff->type == CFF_C)
		is_cvarg_call = TRUE;
	}

if (param_count < expected_count)
	{
NOT_ENOUGH_PARMS:
	po_say_fatal(pcb, "not enough parameters in call to function '%s'",fff->name);
	}

if (pcb->t.toktype == ',')
	{
	po_say_fatal(pcb, "too many parameters in call to function '%s'", fff->name);
	}

po_eat_rparen(pcb);

/* Ok, currently the parameters are (backwards) in the param_exps list and
	the function calling code is in e.	Must reorder things so parameters
	go first in e and then the calling code. */

if (e->left_complex)
	po_copy_code(pcb, &e->ecd, &callcode);

clear_code_buf(pcb, &e->ecd);

exp = param_exps;
while (exp != NULL)
	{
	po_cat_code(pcb, &e->ecd, &exp->ecd);
	exp = exp->next;
	}

if (is_cvarg_call)
	{
	po_code_long(pcb, &e->ecd, OP_LCON, varg_param_size);
	po_code_long(pcb, &e->ecd, OP_LCON, varg_param_count);
	param_size += 2*sizeof(long); /* for stack cleanup instruction later */
	}

po_cat_code(pcb, &e->ecd, &callcode);

idot = e->ctc.ido_type;
if (e->left_complex)
	{
	po_code_op(pcb, &e->ecd, OP_CALLI);
	}
else
	{
	if (fff->type == CFF_C)
		{
		po_code_void_pt(pcb, &e->ecd, po_ccall_ops[idot],
			((C_frame *)fff)->code_pt);
		}
	else
		{
		po_code_void_pt(pcb, &e->ecd, OP_PCALL, fff);
		}
	}

if (param_size > 0)
	{
	po_code_int(pcb, &e->ecd, OP_ADD_STACK, param_size);
	}

if (idot != IDO_VOID)	/* non-void type */
	{
	po_code_op(pcb, &e->ecd, po_find_push_op(pcb,&e->ctc));
	}

e->includes_function = TRUE;
while (param_exps != NULL)
	{
	exp = param_exps->next;
	po_dispose_expframe(pcb, param_exps);
	param_exps = exp;
	}
po_trash_code_buf(pcb, &callcode);
}