On 01.09.2013 20:21, Bernd Oppolzer wrote:
As I understand it now, we have several levels of the compiler:
a) scanning and parsing the source code, which leads to a "tree
representation"
of the units, which IMO is a kind of in-storage-representation of the
source code
(and tables etc.), without much dependencies of the target, if any. I
don't think,
that informations about available registers etc. of the target machine
are necessary
at this level.
Correct. There are only very few exceptions, e.g. on m68k-amiga you can
use the "location" keyword to specify a register location for a
parameter or the result value (whereby of course you need to know which
registers are available).
b) the "tree representation" is translated into a "linear assembly
list", which is
target specific; from previous posts it sounds as if there are generic
methods
which help with this, and those methods of course need information about
the
target platform - but there is no "intermediate language" at this stage
like
in the P-Code case. (I know of other compilers, namely the IBM commercial
ones, which translate in this stage for an abstract target machine which
has
an arbitrary number of registers, and the later "real" code generator
puts it
down to the real number, for example 16, and the missing registers are
simulated in storage). This needs to be examined more.
It looks like this: all nodes are classes that descend from the tnode
class. E.g. for adding two values (ordinals or floats) there is the
taddnode which descends from tbinarynode which in turn descends from
tnode. This taddnode does the general type checking and often also
determines whether the result will be passed in a register, as memory
reference or whatever. Then there is the tcgaddnode which descends from
taddnode and is either able to provide a platform independant
implementation (not the case for taddnode) which uses the general
interface of the code generator or at least provides a few platform
specific helpers and splits the implementation up a bit (in this case
tcgaddnode provides methods "second_addfloat", "second_cmpfloat",
"second_addordinal", etc. which can be implemented by the platform
specific node which is (in case of ARM) called tarmaddnode and is a
descendant of tcgaddnode.
This node usually uses the platform specific taicpu to generate the
abstract assembler instructions.
This seems a bit abstract at first, but with time you get a feeling for
it...
c) the "linear assembly list" is written to files, more or less without
changes
Whereby the specified assembler writer is used.
d) the files are assembled using an external assembler (in our case);
it must be callable from the FPC compiler. There exists an interface for
gas;
interfaces to other assemblers have to be built.
gas is only one example. There are interfaces for a few other assemblers
as well (mostly on i386, but e.g. on ppc-macos (Classic Mac OS) we use
the Apple specific assembler tool)
e) in the same way an external linker is used to link the units together.
Correct.
Regards,
Sven
_______________________________________________
fpc-devel maillist - [email protected]
http://lists.freepascal.org/mailman/listinfo/fpc-devel