Tuesday, February 22, 2022

[SOLVED] Why on many drivers, the return value of functions is handled with variables?

Issue

I see in a lot of drivers code like

static rettype fun(argtype arg) {
    rettype ret;
    // do some stuff and change ret accordingly
    return ret;
}

couldn't that be handled faster when directly returning a value or gotoing when possible? That way you save the space of the return value and an assignation for ret that you'd need to do at least. I'm confused, every help would be nice. Thanks.


Solution

In general, a code structure that looks complicated and is nested with a structure such as:

Calculate some things, look up some things.
if (one thing)
{
    Get some more things.
    if (another thing)
        …
}
else
{
    Get different things.
    if (that thing)
        …
    else
        …
            …
                if (yet another decision)
                    retval = SURE_THAT_IS_FINE;
                else
                    …
            …
        …
    …
}

will be exactly equivalent to the same code with the retval = replaced by return SURE_THAT_IS_FINE. That is because any compiler of normal quality constructs, among other things, a flow graph for the code. Whether the code has a return statement deep inside the nested structure or merely falls out of the nested structure, the very next thing executed is a return from the function. Even with the assignment statement, the compiler will see that retval is used only to return a value from the function, so the compiler will optimize away the assignment—it will merely put the value in the appropriate place to return it from the function and not actually write it to separate memory allocated for retval.

So, a far as the compiler and the generated code is concerned, there will be no difference between these two choices. Then why might we pick one over the other?

Software grows to become complicated, and humans are prone to making mistakes when working with complicated code. One way to reduce errors is to create regular patterns to follow. If we figure out patterns that work, and we follow those patterns when writing our code, then we relieve ourselves of some of the need to analyze all the code while we are writing or modifying it—we can follow the pattern instead of retracing all the codes in our minds multiple times to figure it out. Programming does not require us to follow patterns, but using patterns is a tool to make our work easier or better.

In this case, driver developers may have established a pattern of always assigning retvaland falling through to the end of the driver routine. In some drivers, there might be some final processing code just before the return. For example, there might be code to release resources that were allocated or code to trigger certain things if an error code is being returned. Even there was no such code in the particular drivers you looked at, there may be in others. And following the pattern of always falling through to the end of the routine instead of returning directly serves the purpose of ensuring that this final processing code is always executed, not bypassed.

That is just one example. There could be other reasons for using this pattern.



Answered By - Eric Postpischil
Answer Checked By - Gilberto Lyons (WPSolving Admin)