Beispiel #1
0
/*
 *      analyze and generate best switch statement.
 */
void genxswitch(Statement *stmt)
{ 
	int     oldbreak;
    oldbreak = breaklab;
    breaklab = nextlabel++;
    GenerateSwitch(stmt);
    GenerateCase(stmt->s1);
    GenerateLabel(breaklab);
    breaklab = oldbreak;
}
Beispiel #2
0
/*
 * Generate code for a specific non-virtual operation.
 */
static void GenerateNonVirtual(TreeCCContext *context,
							   const TreeCCNonVirtual *nonVirt,
							   TreeCCOperation *oper)
{
	TreeCCStream *stream;
	TreeCCOperationCase *operCase;
	int number;

	/* Determine which stream to write to */
	if(context->language == TREECC_LANG_JAVA)
	{
		if(oper->className)
		{
			stream = TreeCCStreamGetJava(context, oper->className);
		}
		else
		{
			stream = TreeCCStreamGetJava(context, oper->name);
		}
	}
	else
	{
		stream = oper->source;
	}

	/* Output start declarations for the operation */
	(*(nonVirt->genStart))(context, stream, oper);

	/* If the operation is not inline, then output functions for all cases */
	if((oper->flags & TREECC_OPER_INLINE) == 0)
	{
		number = 1;
		operCase = oper->firstCase;
		while(operCase != 0)
		{
			(*(nonVirt->genCaseFunc))(context, stream, operCase, number);
			operCase->number = number++;
			operCase = operCase->next;
		}
	}

	/* Process split non-virtuals */
	if(oper->numTriggers > 1 && (oper->flags & TREECC_OPER_SPLIT) != 0)
	{
		/* Split the switch statement over multiple levels of functions,
		   so that no single function grows too large */
		AssignTriggerPosns(context, oper);
		GenerateSplitMultiSwitch(context, stream, nonVirt, oper,
							     oper->sortedCases, 0, 1, oper->params, 0);
		(*(nonVirt->genEnd))(context, stream, oper);
		return;
	}

	/* Output the entry point for the operation */
	(*(nonVirt->genEntry))(context, stream, oper);

	/* Generate the switch statement for the outer-most level */
	if(oper->numTriggers <= 1)
	{
		GenerateSwitch(context, stream, nonVirt, oper, oper->firstCase, 0);
	}
	else
	{
		AssignTriggerPosns(context, oper);
		GenerateMultiSwitch(context, stream, nonVirt, oper,
							oper->sortedCases, 0, 1, oper->params, 0);
	}

	/* Output the exit point for the operation */
	(*(nonVirt->genExit))(context, stream, oper);

	/* Output the end declarations for the operation */
	(*(nonVirt->genEnd))(context, stream, oper);
}
Beispiel #3
0
/*
 * Generate code for a "switch" on a trigger.
 */
static TreeCCOperationCase *GenerateSwitch
			(TreeCCContext *context, TreeCCStream *stream,
			 const TreeCCNonVirtual *nonVirt, TreeCCOperation *oper,
			 TreeCCOperationCase *operCase, int triggerNum)
{
	TreeCCParam *param;
	int num, markBit;
	int paramNum;
	TreeCCOperationCase *firstCase;
	TreeCCTrigger *trigger;
	TreeCCNode *node;
	int isEnum;

	/* Generate the head of the switch for this level */
	param = oper->params;
	num = 0;
	paramNum = 1;
	while(param != 0)
	{
		if((param->flags & TREECC_PARAM_TRIGGER) != 0)
		{
			if(num == triggerNum)
			{
				break;
			}
			++num;
		}
		if(!(param->name))
		{
			++paramNum;
		}
		param = param->next;
	}
	if(!param)
	{
		/* Output the code for the case */
		if((oper->flags & TREECC_OPER_INLINE) != 0)
		{
			(*(nonVirt->genCaseInline))(context, stream, operCase,
										triggerNum - 1);
		}
		else
		{
			(*(nonVirt->genCaseCall))(context, stream, operCase,
									  operCase->number, triggerNum - 1);
		}
		return operCase->next;
	}
	node = TreeCCNodeFindByType(context, param->type);
	isEnum = ((node->flags & TREECC_NODE_ENUM) != 0);
	if(param->name)
	{
		(*(nonVirt->genSwitchHead))(context, stream, param->name,
								    triggerNum, isEnum);
	}
	else
	{
		char paramName[64];
		sprintf(paramName, "P%d__", paramNum);
		(*(nonVirt->genSwitchHead))(context, stream, paramName,
									triggerNum, isEnum);
	}

	/* Recurse to handle the next-inner level of switch statements */
	markBit = TREECC_NODE_MARK(triggerNum);
	TreeCCNodeClearMarking(context, markBit);
	firstCase = operCase;
	do
	{
		/* Output the "case" statements to match this operation case */
		trigger = operCase->triggers;
		num = 0;
		while(trigger != 0 && num < triggerNum)
		{
			++num;
			trigger = trigger->next;
		}
		if(trigger)
		{
			if(!GenerateSelectors(context, stream, nonVirt,
							      trigger->node, markBit, triggerNum))
			{
				/* We already output code for this with another case */
				TreeCCErrorOnLine(context->input, operCase->filename,
								  operCase->linenum,
								  "this operation case duplicates another");
			}
		}
		(*(nonVirt->genEndSelectors))(context, stream, triggerNum);

		/* Generate the next level of "switch"'s */
		operCase = GenerateSwitch(context, stream, nonVirt,
								  oper, operCase, triggerNum + 1);

		/* Terminate the "case" statement */
		(*(nonVirt->genEndCase))(context, stream, triggerNum);
	}
	while(operCase != 0 && LevelsMatch(firstCase, operCase, triggerNum));

	/* Generate the end of the switch for this level */
	(*(nonVirt->genEndSwitch))(context, stream, triggerNum);

	/* Return the next case to be handled to the caller */
	return operCase;
}