@section Introduction This chapter is under construction! This chapter describes some of the internals of @command{vbcc} and tries to explainwhat has to be done to write a code generator for @command{vbcc}.However if someone wants to write one, I suggest to contact me first,so that it can be integrated into the source tree. You have to create a new directory for the new target named@file{machines/<target-name>} and write the files @file{machine.c}, @file{machine.h}and @file{machine.dt}. The compiler for this target will be called@command{vbcc<target-name>} and can be built doing a@command{make TARGET=<target-name> bin/vbcc<target-name>}. From now on integer means any of @code{char, short, int, long, long long} or theirunsigned couterparts. Arithmetic means integer or @code{float} or @code{double} or @code{long double}.Elementary type means arithmetic or pointer. Note that this documentation may mention explicit values when introducingsymbolic constants. This is due to copying and pasting from the sourcecode. These values may not be up to date and in some cases can be overridden.Therefore do never use the absolute values but rather the symbolicrepresentations. @section Building vbcc This section deals with the steps necessary to build the typical@command{vbcc} executables from the sources. @subsection Directory Structure The vbcc-directory contains the following important files and directories:@table @file@item vbcc/The main directory containing the compiler sources. @item vbcc/MakefileThe Makefile used to build @command{vbcc}. @item vbcc/frontend/Directory containing the source to @command{vc}, the compiler driver. @item vbcc/machines/<target>/Directory for the @code{<target>} backend. @item vbcc/machines/ucpp/Directory containing the builtin preprocessor. @item vbcc/vsc/Directory containing source to @command{vsc}, the instruction scheduler. @item vbcc/bin/Directory the executables will be placed in.@end table All compiling is done from the main directory. The frontend @command{vc} is not target-dependend and therefore only one version is created. Every available target has at least one subdirectory with its name in @file{vbcc/machines} and contains at least the files @file{machine.h}, @file{machine.c} and @file{machine.dt}. Target-specific object-files will also be stored in that directory. The executables will be placed in @file{vbcc/bin/}. The main compiler will be called @command{vbcc<target>}. @subsection Adapting the Makefile Before building anything you have to insert correct values for @code{CC, NCC, LDFLAGS} and @code{NLDFLAGS} in the @file{Makefile}. @table @code @item CC Here you have to insert a command that invokes an ANSI C compiler you want to use to build vbcc. It must support @option{-D}, @option{-I}, @option{-c} and @option{-o} the same like e.g. @command{vc} or @command{gcc}. Additional options should also be inserted here. E.g. if you are compiling for the Amiga with @command{vbcc} you should add @option{-DAMIGA}. @item LDFLAGS Here you have to add options which are necessary for linking. E.g. some compilers need special libraries for floating-point. @item NCC @itemx NLDFLAGS These are similar to @code{CC} and @code{LDFLAGS} but they must always describe a native compiler, i.e. Programs compiled with @code{NCC/NLDFLAGS} must be executable on the host system. This is needed because during the build programs may have to be executed on the host.@end table An example for the Amiga using @command{vbcc} would be:@example CC = vc -DAMIGA -c99 LDFLAGS = -lmieee NCC = $(CC) NLDFLAGS = $(LDFLAGS)@end example An example for a typical Unix-installation would be:@example CC = cc LDFLAGS = -lm NCC = $(CC) NLDFLAGS = $(LDFLAGS)@end example The following settings are probably necessary for Open/Free/Any BSD i386 systems:@example CC = gcc -D_ANSI_SOURCE LDFLAGS = -lm NCC = $(CC) NLDFLAGS = $(LDFLAGS)@end example @subsection Building vc Note to users of Open/Free/Any BSD i386 systems: You will probably have to useGNU make instead of BSD make, i.e. in the following examples replace "make"with "gmake". Type:@example make bin/vc@end example @subsection Building vsc Type:@example make TARGET=<target> bin/vsc<target>@end example For example:@example make TARGET=alpha bin/vscalpha@end example Omit this step if there is no file @file{machines/<target>/schedule.c}. @subsection Building vbcc Type: @example make TARGET=<target> bin/vbcc<target>@end exampleFor example:@example make TARGET=alpha bin/vbccalpha@end example During the build the program @command{dtgen} will be generated and executed on the host-system. First it will ask you whether you are building a cross-compiler. Answer @code{y} only if you are building a cross-compiler (i.e. a compiler which does not produce code for the same machine it it running on). Note that it does _not_ matter if you are cross-building a compiler, i.e. if you are running on system A and building a B->B compiler by using an A->B compiler then you can answer @code{n}. If you answered @code{y} you will be asked if your system/compiler offers certain datatypes. This refers to the compiler you described with CC in the Makefile. E.g. if @code{CC} is an A->B cross-compiler you have to answer the questions according to B. To each question answer @code{y} or @code{n} depending if such a datatype is available on that compiler. If you answered @code{y} you have to type in the name of that type on the compiler (e.g. @code{signed int}, @code{unsigned char} etc.). If there are not enough datatypes available to build @command{vbcc} an error message will be printed and the build aborts. @subsection Configuring Consult the @command{vbcc}-documentation for information on how to create the necessary config-files. @subsection Building Cross-Compilers As there is often confusion when it comes to cross-building compilers or building cross-compilers, here is what has to be done to cross-build a B->C cross-compiler on system A with only a native A->A compiler available. This is done by first building an A->B compiler and then cross-building the B->C compiler using the A->B compiler. For the first step you use the A->A compiler for @code{CC} as well as @code{NCC}. Now you type:@example make bin/vc make TARGET=B bin/vscB # omit if there is no machines/B/schedule.c make TARGET=B bin/vbccB@end example The questions about datatypes are answered according to A. Then you should write a @file{vc.config} for the @code{vbccB} cross-compiler. Now create a second directory containing all the sources to @command{vbcc} and set @code{CC/LDFLAGS} to @command{vc} using the config-file for vbccB and @code{NCC/NLDFLAGS} to the A->A compiler. Type:@example make bin/vc make TARGET=C bin/vscC # omit if there is no machines/C/schedule.c make TARGET=C bin/vbccC@end example @section The Intermediate Code @command{vbcc} will generate intermediate code for every function and passthis code to the code generator which has to convert it into the desired output. In the future there may be a code generator generator which reads a machinedescription file and generates a code generator from that, but it is notclear whether this could simplify much without taking penalties in thegenerated code.Anyway, this would be a layer on top of the current interface to the codegenerator, so that the interface described in this document would still bevalid and accessible. @subsection General Format The intermediate code is represented as a doubly linked list of quadruples(I am calling them ICs from now on) consisting mainly of an operator, twosource operands and a target. They are represented like this: @example struct IC@{ struct IC *prev; struct IC *next; int code; int typf; int typf2; [...] struct obj q1; struct obj q2; struct obj z; [...] struct ext_ic ext; /* optional */@};@end example The only members relevant to the code generator are@code{prev, next, code, typf, typf2, q1, q2, z} and (optionally) @code{ext_ic}. @code{prev} and @code{next} are pointers to the previous and next IC.The first IC has @code{prev==0} and the last one has @code{next==0}. @code{typf} and @code{typf2} are the type of the operands of this IC.In most ICs all operands have the same type and therefore only @code{typf}is used. However, some ICs have operands of different types (e.g.converting an operand to another type or adding an integer to a pointer).@code{typf2} is used in these cases. Macros are provided which yield the type of an operand.@code{q1typ(), q2typ()} and @code{ztyp()} return the type of the first sourceoperand, the second source operand and the destination, respectively.They have to be passed a pointer to a valid IC as argument. The results areundefined if the IC does not contain the specified operand (e.g. @code{q2typ()}for an IC with only a single operand). The standard types which are defined by default are: @example #define CHAR #define SHORT #define INT #define LONG #define LLONG #define FLOAT #define DOUBLE #define LDOUBLE #define VOID #define POINTER #define ARRAY #define STRUCT #define UNION #define ENUM /* not relevant for code generator */ #define FUNKT @end example and can be additionally or'ed by @example #define UNSIGNED #define CONST #define VOLATILE #define UNCOMPLETE@end example However, only @code{UNSIGNED} is of real importance for the code generator. @code{typf&NQ} yields the type without any qualifiers, @code{typf&NU} yields the type without any qualifiers but @code{UNSIGNED}. It is possible for backends to define additional types. @xref{exttypes}for documentation on how to extend the type system. @node operands@subsection Operands @code{q1, q2} and @code{z} are the source1 (quelle1 in German), source2 andtarget (ziel) operands, respectively.If a result has to be computed, it always will be stored in the object @code{z}and the objects @code{q1} and @code{q2} usually may not be destroyed duringthis operation (unless they are aliased with the destination). The objects are described by this structure: @example struct obj@{ int flags; int reg; int dtyp; struct Var *v; struct AddressingMode *am; union atyps@{ zchar vchar; zchar vuchar; zshort vshort; zushort vushort; zint vint; zuint vuint; zlong vlong; zulong vulong; zllong vllong; zullong vullong; zmax vmax; zumax vumax; zfloat vfloat; zdouble vdouble; zldouble vldouble; @} val;@}; @end example @code{flags} specifies the kind of object. It can be a combination of @table @code @item #define KONST 1 The object is a constant. Its value is in the corresponding (to @code{typf} or @code{typf2}) member of @code{val}. @item #define VAR 2 The object is a variable. The pointer to its @code{struct Var} is in @code{v}. @code{val.vlong} vontains an offset that has to be added to it. Fur further details, @pxref{Variables}. @item #define DREFOBJ 32 The content of the location in memory the object points to is used. @code{dtyp} contains the type of the pointer. In systems with only one pointer type, this will always be @code{POINTER}. @item #define REG 64 The object is a register. @code{reg} contains its number. @item #define VARADR 128 The address of the object is to be used. Only together with static variables (i.e. @code{storage_class == STATIC} or @code{EXTERN}). @end table The possible combinations of these flags should be: @itemize @item @code{0} (no object) @item @code{KONST} @item @code{KONST|DREFOBJ} @item @code{REG} @item @code{VAR} @item @code{VAR|REG} @item @code{REG|DREFOBJ} @item @code{KONST|DREFOBJ} @item @code{VAR|DREFOBJ} @item @code{VAR|REG|DREFOBJ} @item @code{VAR|VARADR}@end itemize Also some other bits which are not relevant to the code generator may be set. Constants will usually be in @code{q2} if possible. One of the sources alwaysis not constant and the target is always an lvalue.The types of the operands can be queried using the macros@code{q1typ(), q2typ()} and @code{ztyp()}.In most cases (i.e. when not explicitly stated) the type is an elementary type(i.e. arithmetic or pointer). @code{am} can be used to store information on special addressing modes.This has to be handled by the by the code generator. However @code{am} has to be 0or has to point to a @code{struct AddressingMode} that was allocated using @code{malloc()}when the code generator returns. @code{struct AddressingMode} has to be definedin @file{machine.h}. @code{val} stores either the value of the object if it is a constant or anoffset if it is a variable. @code{code} specifies the operation. Fur further details @pxref{operations}. @node Variables@subsection Variables A @code{struct Var} looks like: @example struct Var@{ int storage_class; [...] char *identifier; [...] zmax offset; struct Typ *vtyp; [...] char *vattr; unsigned long tattr; /* optional */ @};@end example The relevant entries are: @table @code @item identifier The name of the variable. Usually only of interest for variables with external-linkage. @item storage_class One of: @example #define AUTO 1 #define REGISTER 2 #define STATIC 3 #define EXTERN 4 #define TYPEDEF 5 /* not relevant */ @end example The backend should use the macros @code{isauto(), isstatic()} and @code{isextern()} to check which category a variable falls into. @item offset Contains an offset relative to the beginning of the variable's storage. Used, for example, when accessing members of structures. @item vtyp The type of the variable (@pxref{compositetypes}). @item vattr A string with attributes used in the declaration of the variable. @xref{targetattributes} for further details. @item tattr Flags used when declaring the variable. @xref{targetattributes} for further details.@end table If the variable is not assigned to a register (i.e. bit @code{REG} is not set in the flags of the corresponding @code{struct obj}) then the variable can be addressed in the following ways (with examples of 68k-code): @table @code @item isauto(storage_class) != 0 @code{offset} contains the offset inside the local-variables section. The code generator must decide how it's going to handle the activation record. If @code{offset < 0} then the variable is a function argument on theLines 1–500 of 2830. Load more
@section Introduction This chapter is under construction! This chapter describes some of the internals of @command{vbcc} and tries to explain what has to be done to write a code generator for @command{vbcc}. However if someone wants to write one, I suggest to contact me first, so that it can be integrated into the source tree. You have to create a new directory for the new target named @file{machines/<target-name>} and write the files @file{machine.c}, @file{machine.h} and @file{machine.dt}. The compiler for this target will be called @command{vbcc<target-name>} and can be built doing a @command{make TARGET=<target-name> bin/vbcc<target-name>}. From now on integer means any of @code{char, short, int, long, long long} or their unsigned couterparts. Arithmetic means integer or @code{float} or @code{double} or @code{long double}. Elementary type means arithmetic or pointer. Note that this documentation may mention explicit values when introducing symbolic constants. This is due to copying and pasting from the source code. These values may not be up to date and in some cases can be overridden. Therefore do never use the absolute values but rather the symbolic representations. @section Building vbcc This section deals with the steps necessary to build the typical @command{vbcc} executables from the sources. @subsection Directory Structure The vbcc-directory contains the following important files and directories: @table @file @item vbcc/ The main directory containing the compiler sources. @item vbcc/Makefile The Makefile used to build @command{vbcc}. @item vbcc/frontend/ Directory containing the source to @command{vc}, the compiler driver. @item vbcc/machines/<target>/ Directory for the @code{<target>} backend. @item vbcc/machines/ucpp/ Directory containing the builtin preprocessor. @item vbcc/vsc/ Directory containing source to @command{vsc}, the instruction scheduler. @item vbcc/bin/ Directory the executables will be placed in. @end table All compiling is done from the main directory. The frontend @command{vc} is not target-dependend and therefore only one version is created. Every available target has at least one subdirectory with its name in @file{vbcc/machines} and contains at least the files @file{machine.h}, @file{machine.c} and @file{machine.dt}. Target-specific object-files will also be stored in that directory. The executables will be placed in @file{vbcc/bin/}. The main compiler will be called @command{vbcc<target>}. @subsection Adapting the Makefile Before building anything you have to insert correct values for @code{CC, NCC, LDFLAGS} and @code{NLDFLAGS} in the @file{Makefile}. @table @code @item CC Here you have to insert a command that invokes an ANSI C compiler you want to use to build vbcc. It must support @option{-D}, @option{-I}, @option{-c} and @option{-o} the same like e.g. @command{vc} or @command{gcc}. Additional options should also be inserted here. E.g. if you are compiling for the Amiga with @command{vbcc} you should add @option{-DAMIGA}. @item LDFLAGS Here you have to add options which are necessary for linking. E.g. some compilers need special libraries for floating-point. @item NCC @itemx NLDFLAGS These are similar to @code{CC} and @code{LDFLAGS} but they must always describe a native compiler, i.e. Programs compiled with @code{NCC/NLDFLAGS} must be executable on the host system. This is needed because during the build programs may have to be executed on the host. @end table An example for the Amiga using @command{vbcc} would be: @example CC = vc -DAMIGA -c99 LDFLAGS = -lmieee NCC = $(CC) NLDFLAGS = $(LDFLAGS) @end example An example for a typical Unix-installation would be: @example CC = cc LDFLAGS = -lm NCC = $(CC) NLDFLAGS = $(LDFLAGS) @end example The following settings are probably necessary for Open/Free/Any BSD i386 systems: @example CC = gcc -D_ANSI_SOURCE LDFLAGS = -lm NCC = $(CC) NLDFLAGS = $(LDFLAGS) @end example @subsection Building vc Note to users of Open/Free/Any BSD i386 systems: You will probably have to use GNU make instead of BSD make, i.e. in the following examples replace "make" with "gmake". Type: @example make bin/vc @end example @subsection Building vsc Type: @example make TARGET=<target> bin/vsc<target> @end example For example: @example make TARGET=alpha bin/vscalpha @end example Omit this step if there is no file @file{machines/<target>/schedule.c}. @subsection Building vbcc Type: @example make TARGET=<target> bin/vbcc<target> @end example For example: @example make TARGET=alpha bin/vbccalpha @end example During the build the program @command{dtgen} will be generated and executed on the host-system. First it will ask you whether you are building a cross-compiler. Answer @code{y} only if you are building a cross-compiler (i.e. a compiler which does not produce code for the same machine it it running on). Note that it does _not_ matter if you are cross-building a compiler, i.e. if you are running on system A and building a B->B compiler by using an A->B compiler then you can answer @code{n}. If you answered @code{y} you will be asked if your system/compiler offers certain datatypes. This refers to the compiler you described with CC in the Makefile. E.g. if @code{CC} is an A->B cross-compiler you have to answer the questions according to B. To each question answer @code{y} or @code{n} depending if such a datatype is available on that compiler. If you answered @code{y} you have to type in the name of that type on the compiler (e.g. @code{signed int}, @code{unsigned char} etc.). If there are not enough datatypes available to build @command{vbcc} an error message will be printed and the build aborts. @subsection Configuring Consult the @command{vbcc}-documentation for information on how to create the necessary config-files. @subsection Building Cross-Compilers As there is often confusion when it comes to cross-building compilers or building cross-compilers, here is what has to be done to cross-build a B->C cross-compiler on system A with only a native A->A compiler available. This is done by first building an A->B compiler and then cross-building the B->C compiler using the A->B compiler. For the first step you use the A->A compiler for @code{CC} as well as @code{NCC}. Now you type: @example make bin/vc make TARGET=B bin/vscB # omit if there is no machines/B/schedule.c make TARGET=B bin/vbccB @end example The questions about datatypes are answered according to A. Then you should write a @file{vc.config} for the @code{vbccB} cross-compiler. Now create a second directory containing all the sources to @command{vbcc} and set @code{CC/LDFLAGS} to @command{vc} using the config-file for vbccB and @code{NCC/NLDFLAGS} to the A->A compiler. Type: @example make bin/vc make TARGET=C bin/vscC # omit if there is no machines/C/schedule.c make TARGET=C bin/vbccC @end example @section The Intermediate Code @command{vbcc} will generate intermediate code for every function and pass this code to the code generator which has to convert it into the desired output. In the future there may be a code generator generator which reads a machine description file and generates a code generator from that, but it is not clear whether this could simplify much without taking penalties in the generated code. Anyway, this would be a layer on top of the current interface to the code generator, so that the interface described in this document would still be valid and accessible. @subsection General Format The intermediate code is represented as a doubly linked list of quadruples (I am calling them ICs from now on) consisting mainly of an operator, two source operands and a target. They are represented like this: @example struct IC@{ struct IC *prev; struct IC *next; int code; int typf; int typf2; [...] struct obj q1; struct obj q2; struct obj z; [...] struct ext_ic ext; /* optional */ @}; @end example The only members relevant to the code generator are @code{prev, next, code, typf, typf2, q1, q2, z} and (optionally) @code{ext_ic}. @code{prev} and @code{next} are pointers to the previous and next IC. The first IC has @code{prev==0} and the last one has @code{next==0}. @code{typf} and @code{typf2} are the type of the operands of this IC. In most ICs all operands have the same type and therefore only @code{typf} is used. However, some ICs have operands of different types (e.g. converting an operand to another type or adding an integer to a pointer). @code{typf2} is used in these cases. Macros are provided which yield the type of an operand. @code{q1typ(), q2typ()} and @code{ztyp()} return the type of the first source operand, the second source operand and the destination, respectively. They have to be passed a pointer to a valid IC as argument. The results are undefined if the IC does not contain the specified operand (e.g. @code{q2typ()} for an IC with only a single operand). The standard types which are defined by default are: @example #define CHAR #define SHORT #define INT #define LONG #define LLONG #define FLOAT #define DOUBLE #define LDOUBLE #define VOID #define POINTER #define ARRAY #define STRUCT #define UNION #define ENUM /* not relevant for code generator */ #define FUNKT @end example and can be additionally or'ed by @example #define UNSIGNED #define CONST #define VOLATILE #define UNCOMPLETE @end example However, only @code{UNSIGNED} is of real importance for the code generator. @code{typf&NQ} yields the type without any qualifiers, @code{typf&NU} yields the type without any qualifiers but @code{UNSIGNED}. It is possible for backends to define additional types. @xref{exttypes} for documentation on how to extend the type system. @node operands @subsection Operands @code{q1, q2} and @code{z} are the source1 (quelle1 in German), source2 and target (ziel) operands, respectively. If a result has to be computed, it always will be stored in the object @code{z} and the objects @code{q1} and @code{q2} usually may not be destroyed during this operation (unless they are aliased with the destination). The objects are described by this structure: @example struct obj@{ int flags; int reg; int dtyp; struct Var *v; struct AddressingMode *am; union atyps@{ zchar vchar; zchar vuchar; zshort vshort; zushort vushort; zint vint; zuint vuint; zlong vlong; zulong vulong; zllong vllong; zullong vullong; zmax vmax; zumax vumax; zfloat vfloat; zdouble vdouble; zldouble vldouble; @} val; @}; @end example @code{flags} specifies the kind of object. It can be a combination of @table @code @item #define KONST 1 The object is a constant. Its value is in the corresponding (to @code{typf} or @code{typf2}) member of @code{val}. @item #define VAR 2 The object is a variable. The pointer to its @code{struct Var} is in @code{v}. @code{val.vlong} vontains an offset that has to be added to it. Fur further details, @pxref{Variables}. @item #define DREFOBJ 32 The content of the location in memory the object points to is used. @code{dtyp} contains the type of the pointer. In systems with only one pointer type, this will always be @code{POINTER}. @item #define REG 64 The object is a register. @code{reg} contains its number. @item #define VARADR 128 The address of the object is to be used. Only together with static variables (i.e. @code{storage_class == STATIC} or @code{EXTERN}). @end table The possible combinations of these flags should be: @itemize @item @code{0} (no object) @item @code{KONST} @item @code{KONST|DREFOBJ} @item @code{REG} @item @code{VAR} @item @code{VAR|REG} @item @code{REG|DREFOBJ} @item @code{KONST|DREFOBJ} @item @code{VAR|DREFOBJ} @item @code{VAR|REG|DREFOBJ} @item @code{VAR|VARADR} @end itemize Also some other bits which are not relevant to the code generator may be set. Constants will usually be in @code{q2} if possible. One of the sources always is not constant and the target is always an lvalue. The types of the operands can be queried using the macros @code{q1typ(), q2typ()} and @code{ztyp()}. In most cases (i.e. when not explicitly stated) the type is an elementary type (i.e. arithmetic or pointer). @code{am} can be used to store information on special addressing modes. This has to be handled by the by the code generator. However @code{am} has to be 0 or has to point to a @code{struct AddressingMode} that was allocated using @code{malloc()} when the code generator returns. @code{struct AddressingMode} has to be defined in @file{machine.h}. @code{val} stores either the value of the object if it is a constant or an offset if it is a variable. @code{code} specifies the operation. Fur further details @pxref{operations}. @node Variables @subsection Variables A @code{struct Var} looks like: @example struct Var@{ int storage_class; [...] char *identifier; [...] zmax offset; struct Typ *vtyp; [...] char *vattr; unsigned long tattr; /* optional */ @}; @end example The relevant entries are: @table @code @item identifier The name of the variable. Usually only of interest for variables with external-linkage. @item storage_class One of: @example #define AUTO 1 #define REGISTER 2 #define STATIC 3 #define EXTERN 4 #define TYPEDEF 5 /* not relevant */ @end example The backend should use the macros @code{isauto(), isstatic()} and @code{isextern()} to check which category a variable falls into. @item offset Contains an offset relative to the beginning of the variable's storage. Used, for example, when accessing members of structures. @item vtyp The type of the variable (@pxref{compositetypes}). @item vattr A string with attributes used in the declaration of the variable. @xref{targetattributes} for further details. @item tattr Flags used when declaring the variable. @xref{targetattributes} for further details. @end table If the variable is not assigned to a register (i.e. bit @code{REG} is not set in the flags of the corresponding @code{struct obj}) then the variable can be addressed in the following ways (with examples of 68k-code): @table @code @item isauto(storage_class) != 0 @code{offset} contains the offset inside the local-variables section. The code generator must decide how it's going to handle the activation record. If @code{offset < 0} then the variable is a function argument on the