Why is backpatching needed during intermediate code generation? 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 &lt; 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.
Suppose you encounter a jump instruction "goto L1" before encountering the label L1 itself. The solution you propose (as far as I understand) is to reserve a location M1 in memory at which L1 will be stored, and to translate "goto L1" into an instruction of the form "jump to the address stored at address M1". Later on, upon reaching L1, you update location M1 with the address of L1.

This is a form of "runtime backpatching", in which the processor itself is doing the backpatching when running the code. Accessing memory tends to be slow, and so it is much better to hardcode addresses, shifting the effort from runtime to compile time. This is where backpatching comes in. When encountering "goto L1", the compiler will note that the address is missing, and will fill it in later, when the address of L1 is known.