14.7. The Coward's Way Out

Before we get into the details (and potential complexity) of type conversion, I'd like you to see that there is one super-simple way to solve the problem: simply promote every variable to a long integer when we load it!

This takes the addition of only one line to LoadVar, although if we are not going to COMPLETELY ignore efficiency, it should be guarded by an IF test. Here is the modified version:

{ Load a Variable to Primary Register }
procedure LoadVar(Name, Typ: char);
begin
   if Typ <> 'L' then
      EmitLn('CLR.L D0');
   Move(Typ, Name + '(PC)', 'D0');
end;

Note

Note that StoreVar needs no similar change.

If you run some tests with this new version, you will find that everything works correctly now, albeit sometimes inefficiently. For example, consider the case a=b (for the same declarations shown above). Now the generated code turns out to be:

     CLR.L D0
     MOVE.W B(PC),D0
     LEA  A(PC),A0
     MOVE.B D0,(A0)

In this case, the CLR turns out not to be necessary, since the result is going into a byte-sized variable. With a little bit of work, we can do better. Still, this is not bad, and it typical of the kinds of inefficiencies that we've seen before in simple-minded compilers.

I should point out that, by setting the high bits to zero, we are in effect treating the numbers as UNSIGNED integers. If we want to treat them as signed ones instead (the more likely case) we should do a sign extension after the load, instead of a clear before it. Just to tie this part of the discussion up with a nice, red ribbon, let's change LoadVar as shown below:

{ Load a Variable to Primary Register }
procedure LoadVar(Name, Typ: char);
begin
   if Typ = 'B' then
      EmitLn('CLR.L D0');
   Move(Typ, Name + '(PC)', 'D0');
   if Typ = 'W' then
      EmitLn('EXT.L D0');
end;

With this version, a byte is treated as unsigned (as in Pascal and C), while a word is treated as signed.