C Control Statements in ANT

This document discusses how several of the basic C control flow statements can be translated into ANT. These are by no means the best translations- for specific algorithms, there might be much better ways to do the same things. However, these translations are fairly generic and are a good place to start.


Rules of the Game

For the sake of argument, I'll assume that the following conditions are always true:

  1. The evaluation of a condition always ends with the result in register r2.

    Of course, when you're actually programming in ANT, you may or may not decide to adopt a convention like this, or you may choose another convention entirely. However, if I assume that this condition is always met, then I can make other simplifying assumptions. Replace r2 with the appropriate register in your own code.

  2. I can use register r3 for whatever purpose I want. In this case, I'm usually going to use it to hold constants corresponding to the labels I want to branch to. Again, replace r3 with the appropriate register in your own code.

  3. The programmer has a endless supply of "matching" and uniquely named labels that he or she can use. For example, the if-else construct described here requires two new labels, denoted if_else_label and if_end_label. The programmer can always pick suitable names for these labels, and plug them in as necessary. This makes it possible to have any number of if-else statements in your program, without getting confused as to which if_else_label is related to a particular if_end_else label.


if-else

The if-else statement is the most fundamental control flow statement.

if

First, consider the if statement without an else.

The following C code:

	if ( condition ) {
		statements
	}

corresponds to the following ANT code:

		# ANT code for the condition expression,
		# leaving the result in register r2.

		lc	r3, $if_end_label
		beq	r3, r2, r0

		# ANT code for the statements.

	if_end_label:

if-else

Now we'll generalize the if statement to include an else:

The following C code:

	if ( condition ) {
		if-statements
	}
	else {
		else-statements
	}

corresponds to the following ANT code:

		# ANT code for the condition expression,
		# leaving the result in r2.

		lc	r3, $if_else_label
		beq	r3, r2, r0

		# ANT code for the if-statements.

		lc	r3, $if_end_label
		beq	r3, r0, r0

	if_else_label:

		# ANT code for the else-statements.

	if_end_label:


while

The following C code:

	while ( condition ) {
		statements
	}
corresponds to the following ANT code:

	while_start_label:
	
		# ANT code for the condition expr, leaving
		# the result in r2.

		lc	r3, $while_end_label
		beq	r3, r2, r0

		# ANT code for the statements.

		lc	r3, $which_start_label
		beq	r3, r0, r0

	while_end_label:
A C break statement in a while loop corresponds to the following ANT instructions:

		lc	r3, $while_end_label
		beq	r3, r0, r0

A C continue statement in a while loop corresponds to the following ANT instructions:

		lc	r3, $while_start_label
		beq	r3, r0, r0


do-while

The following C code:

	do {
		statements
	} while ( condition );

corresponds to the following ANT code:

	do_start_label:
	
		# ANT code for the statements.

	do_cond_label:

		# ANT code for the condition expr, leaving
		# the result in r2.

		lc	r3, $do_end_label
		beq	r3, r2, r0

		lc	r3, $do_start_label
		beq	r3, r0, r0

	do_end_label:

A C break statement in a do-while loop corresponds to the following ANT instructions:

		lc	r3, $do_end_label
		beq	r3, r0, r0

A C continue statement in a do-while loop corresponds to the following ANT instruction:

		lc	r3, $do_cond_label
		beq	r3, r0, r0


for

The following C code:

	for ( init ; condition ; incr ) {
		statements
	}

corresponds to the following ANT code:


		# ANT code for the init expression.

	for_start_label:

		# ANT code for the condition expr, leaving
		# the result in r2.

		lc	r3, $for_end_label
		beq	r3, r2, r0

		# ANT code for the statements.

		# ANT code for the incr expression.

		lc	r3, $for_start_label
		beq	r3, r0, r0

	for_end_label:

A C break statement in a for loop corresponds to the following ANT instructions:

		lc	r3, $for_end_label
		beq	r3, r0, r0

A C continue statement in a for loop corresponds to the following ANT instruction:

		lc	r3, $for_start_label
		beq	r3, r0, r0


switch statements

The following C code:

	switch ( expr ) {
		case const1:
			statement1
		case const2:
			statement2

		...

		case constN:
			statementN

		/* The next two lines are optional: */
		default:
			default-statement

	}

corresponds to the following ANT code:


		# ANT code to compute expr.
		# Assume that this leaves the value in r2.
		# Assume that we have register r4 to play with.

		lc	r4, const1
		lc	r3, $switch_label_1
		beq	r3, r2, r4

		lc	r4, const2
		lc	r3, $switch_label_2
		beq	r3, r2, r4

		...

		lc	r4, constN
		lc	r3, $switch_label_N
		beq	r3, r2, r4

		# If there is a default, then add the following line;
		lc	r3, $switch_default
		beq	r3, r0, r0

		# Otherwise, add the following line instead:
		lc	r3, $switch_end_label
		beq	r3, r0, r0

	switch_label_1:
		# ANT code to compute statement1.

	switch_label_2:
		# ANT code to compute statement2.

		...

	switch_label_N:
		# ANT code to compute statementN.


		# If there's a default:
	switch_default:
		# ANT code to compute default-statement.

	switch_end_label:

A C break statement in a switch corresponds to the following ANT instruction:

		lc	r3, $switch_end_label
		beq	r3, r0, r0

Note that if we follow the method of implementing a switch described above, evaluation will "fall through" cases, exactly as it does in C, unless break statements are added.


Short-Circuit Evaluation of Logical Expressions

Short-circuit &&

The following C code:

	cond1 && cond2

corresponds to the following ANT code:


		# ANT code to compute cond1.
		# Assume that this leaves the value in r2.

		# If r2 is zero, we're finished (and the
		#	result is FALSE).

		lc	r3, $and_end
		beq	r3, r2, r0

		# ANT code to compute cond2.
		# Assume that this leaves the value in r2.

	and_end:

This code (as suggested by Aurelio Teleman) takes advantage of the fact that the value residing in r2 (after the last of whichever of cond1 or cond2 is evaluated) is the truth value of the expression as a whole. Therefore, if we want the truth value to reside in r2, then we're already finished. Otherwise, we can use an add instruction to copy the contents of r2 to the appropriate register.

Short-circuit ||

The following C code:

	cond1 || cond2

corresponds to the following ANT code:


		# ANT code to compute cond1.
		# Assume that this leaves the value in r2.

		# If r2 is zero, we're we're not finished (and need to
		# do cond2).

		lc	r3, $or_cond2
		beq	r3, r2, r0

		# Otherwise, we are finished and we can jump right to
		# the end of the or.

		lc	r3, $or_end
		beq	r3, r0, r0

	or_cond2:

		# ANT code to compute cond2.
		# Assume that this leaves the value in $t0.

	or_end:

Once again, this code can take advantage of the fact that the value residing in r2 (after the last of whichever of cond1 or cond2 is evaluated) is the truth value of the expression as a whole. Therefore, if we want the truth value to reside in r2, then we're already finished. Otherwise, we can use an add instruction to copy the contents of r2 to the appropriate register.


Please bring any errors or inconsistencies in this document to the attention of the author.

Dan Ellard - ellard@deas.harvard.edu