Code generation for "if" statements - compilers

4.1k views Asked by At

I am in the middle of developing a compiler for a C like language and am having some difficulties in the semantic analysis and code generation phases. My questions are the following: 1) For an if statement, the following is the syntax:

if (expression) then
statement1;
statement2;
else
statement3;
end if;

Now, in my target code, it has to be a 3-address code with go to statements, so it should

look something like:
if (Rx)  // Rx is the register where the expression is evaluated and stored
go to X1 //for if part
X2 // for else part;

So now, my question is, how do I generate the addresses for "go to" statements?

2) This question is about semantic analysis: I have been able to build and use a symbol table for a single function. What is the approach I should be using to build symbol tables for function calls? In other words for different lexical levels? I know this should somehow involve having multiple trees. One tree for one function. But what's the approach to point to a different tree from somewhere in the middle of a program?

I'm a beginner and thus any suggestions/thoughts would be greatly appreciated.

2

There are 2 answers

4
SK-logic On

Are you generating the code immediately, without an "assembler" pass which will resolve symbolic labels? In this case you have to build a table of all the labels and branching instructions, and then backpatch your code once all the labels are generated.

4
Patrick On

It depends on how and when your compiler will generate code.

If your compiler generates the code sequentially (from the first line of the code to the last one), then the only thing you can do is to remember the places where you want to jump to (store them in a table), and patch the code after everything has been generated.

If your compiler generates the code bottom-up (from the most inside statement to the most outside statement), and your underlying machine (physical or virtual) supports relative jumps, then you can simply generate the relative jumps when generating the code. For example.

Suppose you have this piece of code:

if (condition) then
   someexpressionsA
else
   someexpressionsB
endif;

The bottom-up compilation means that the code will be generated like this:

  • first the code for someexpressionsA
  • then the code for someexpressionsB
  • then the code for the if-then-else-endif statement

Suppose that our compiler has generated the code for someexpressionsA, called codeblockA (same for B). Then the code for the if-then-else-endif statement can be written like this (pseudo code):

  • Check condition
  • if condition is false jump sizeof(codeblockA+1) instructions further
  • codeblockA
  • jump sizeof(codeblockB) further
  • codeblockB

Things might get trickier if the condition contains multiple conditions (and, or, ...) but the example above should get you started.