In this page, it's written that a tail-call is when a call occurs in the end of a function. This is incorrect, a tail-call is when, in assembly, a CALL occurs before RET.
Code: Select all
unsigned long long Factorial(unsigned start) {
if (start > 1) {
return Factorial(start - 1) * start;
} // if
return 1;
} // Factorial(start)
Now the page also writes:
Code: Select all
unsigned long long Factorial(unsigned start) {
if (start <= 1) {
return 1;
} // if
return start * Factorial(start - 1);
} // Factorial(start)
Code: Select all
CMP start,1
JMP.HI _endofblock
MOV return_value, 1
RET
_endofblock:
SUB tmp, start, 1
PUSH tmp
CALL Factorial
MUL return_value, return_value, start
RET
Now an example of a tail-call would include:
Code: Select all
function foo(data) {
a(data);
return b(data);
}
Code: Select all
PUSH data
CALL a
PUSH data #assuming this is needed
CALL b
RET
Code: Select all
PUSH data
CALL a
PUSH data #assuming this is needed
JMP b
Contrary to what the said page claims, a tail call doesn't need to be at the tail of the code:
Code: Select all
function bar(data) {
if ( a(data) ) {
return b(data);
}
return c(data);
}
Code: Select all
PUSH data
CALL a
TEST return_value
JMP.FALSE _endofblock
PUSH data
CALL b
RET
_endofblock:
PUSH data
CALL c
RET
Code: Select all
PUSH data
CALL a
TEST return_value
JMP.FALSE _endofblock
PUSH data
JMP b
_endofblock:
PUSH data
JMP c
Code: Select all
function foo()
{
int myInteger = bar();
return myInteger;
}
Code: Select all
CALL bar
MOV myInteger, return_value
MOV return_value, myInteger
RET
Code: Select all
CALL bar
RET
Code: Select all
JMP bar
Code: Select all
unsigned long long Factorial(unsigned start) {
if (start <= 1) {
return 1;
} // if
return start * Factorial(start - 1);
} // Factorial(start)
Code: Select all
CMP start,1
JMP.HI _endofblock
MOV return_value, 1
RET
_endofblock:
SUB tmp, start, 1
PUSH tmp
CALL Factorial
MUL return_value, return_value, start
RET
Now of course, this also depends on the exact architecture, but as I said, the way the instructions CALL, RET and JMP work are usually the same, so most of the above examples with pseudo-assembly would still work on most real architectures.
If you, the person reading this, are a moderator or anyone else with the privilege to modify the wiki, I ask of you to correct this page, please. Thanks in advance.
Source: https://en.wikipedia.org/wiki/Tail_call