In compiler design, control-flow statements are translated to sequences of three-address-code (3AC) instructions a lot of which are jump statements. A 3AC instruction of the jumping type could be an unconditional jump in the form of a goto statement with a target label as its argument, such as
goto L1
or it may be a conditional jump in the form of an if statement, as in
if a < b goto L1
Now when the compiler generates a 3AC jump instruction, the target label is available to it in the form of an inherited attribute ( which I assume is a pointer to an object/structure and so we could think of it as a pointer to a variable ).
Now, the labels passed to say, an if-else statement as inherited attributes would also be then attached to certain target instructions after the if-else construct that used those labels has been translated.
Suppose, a label L1 has been used a lot of times before in constructs that have now been translated. Now suppose that label has to be attached to say a target assignment statement (the next instruction to be emitted) whose index is in the array of instructions is 137 (because there are 137 3AC instructions already stored in the quadruples array). Then at this point of time the variable L1 would get the value 137 and so all the earlier uses of L1 would also now get the value of L1 (because the variable pointed to by them now gets a value).
And so in this way we have translated control-flow statements in one pass and there is no need for backpatching to reduce the number of passes further.
I don’t understand why what I just wrote wouldn’t work and without backpatching two passes would be required to attach labels to their correct instructions.