Subsections

- 1 Register Conventions
  - 1 accumulator register
  - 2 accumulator 64-bit register
  - 3 float result register
  - 4 self register
  - 5 frame pointer register
  - 6 stack pointer register
  - 7 scratch registers
  - 8 Processor mapping of registers
- 2 Name mangling
  - 1 Mangled names for data blocks
  - 2 Mangled names for code blocks
  - 3 Modifying the mangled names
- 3 Calling mechanism
- 4 Nested procedure and functions
- 5 Constructor and Destructor calls
- 6 Entry and exit code
  - 1 Intel 80x86 standard routine prologue / epilogue
  - 2 Motorola 680x0 standard routine prologue / epilogue
- 7 Parameter passing
  - 1 Parameter alignment
  - 2 Processor limitations

#
6 Code issues

This chapter gives detailed information on the generated code by Free Pascal. It can be useful to write external object files which will be linked to Free Pascal created code blocks.

#
1 Register Conventions

The compiler has different register conventions, depending on the target processor used; some of the registers have specific uses during the code generation. The following section describes the generic names of the registers on a platform per platform basis. It also indicates what registers are used as scratch registers, and which can be freely used in assembler blocks.

## 1 accumulator register

The accumulator register is at least a 32-bit integer hardware register, and is used to return results of function calls which return integral values.

## 2 accumulator 64-bit register

The accumulator 64-bit register is used in 32-bit environments and is defined as the group of registers which will be used when returning 64-bit integral results in function calls. This is a register pair.

## 3 float result register

This register is used for returning floating point values from functions.

## 4 self register

The self register contains a pointer to the actual object or class. This register gives access to the data of the object or class, and the VMT pointer of that object or class.

## 5 frame pointer register

The frame pointer register is used to access parameters in subroutines, as well as to access local variables. References to the pushed prameters and local variables are constructed using the frame pointer. .

## 6 stack pointer register

The stack pointer is used to give the address of the stack area, where the local variables and parameters to subroutines are stored.

## 7 scratch registers

Scratch registers are those which can be used in assembler blocks, or in external object files without requiring any saving before usage.

## 8 Processor mapping of registers

This indicates what registers are used for what purposes on each of the processors supported by Free Pascal. It also indicates which registers can be used as scratch registers.

### 1 Intel 80x86 version

Table: Intel 80x86 Register table
Generic register name | CPU Register name
accumulator | EAX
accumulator (64-bit) high / low | EDX:EAX
float result | FP(0)
self | ESI
frame pointer | EBP
stack pointer | ESP
scratch regs. | N/A

### 2 Motorola 680x0 version

Table: Motorola 680x0 Register table
Generic register name | CPU Register name
accumulator | D0
accumulator (64-bit) high / low | D0:D1
float result | FP0
self | A5
frame pointer | A6
stack pointer | A7
scratch regs. | D0, D1, A0, A1, FP0, FP1

#
2 Name mangling

Contrary to most C compilers and assemblers, all labels generated to pascal variables and routines have mangled names. This is done so that the compiler can do stronger type checking when parsing the pascal code. It also permits function and procedure overloading.

## 1 Mangled names for data blocks

The rules for mangled names for variables and typed constants are as follows:

- All variable names are converted to upper case
- Variables in the main program or private to a unit have an _ prepended to their names
- Typed constants in the main program have an TC__ prepended to their names
- Public variables in a unit have their unit name prepended to them : U_UNITNAME_
- Public and private typed constants in a unit have their unit name prepended to them :TC__UNITNAME$$

Currently, in Free Pascal v1.0, if you declare a variable in unit name `tunit`, with the name `_a`, and you declare the same variable with name `a` in unit name `tunit_`, you will get the same mangled name. This is a limitation of the compiler which will be fixed in release v1.1.

Examples

    unit testvars;

    interface

    const
     publictypedconst : integer = 0;
    var
     publicvar : integer;

    implementation
    const
     privatetypedconst : integer = 1;
    var
     privatevar : integer;

    end.

Will give the following assembler output under GNU as :

    	.file "testvars.pas"

    .text

    .data
    # [6] publictypedconst : integer = 0;
    .globl	TC__TESTVARS$$_PUBLICTYPEDCONST
    TC__TESTVARS$$_PUBLICTYPEDCONST:
    	.short	0
    # [12] privatetypedconst : integer = 1;
    TC__TESTVARS$$_PRIVATETYPEDCONST:
    	.short	1

    .bss
    # [8] publicvar : integer;
    	.comm	U_TESTVARS_PUBLICVAR,2
    # [14] privatevar : integer;
    	.lcomm	_PRIVATEVAR,2

## 2 Mangled names for code blocks

The rules for mangled names for routines are as follows:

- All routine names are converted to upper case.
- Routines in a unit have their unit name prepended to them : _UNITNAME$$_
- All Routines in the main program have a _ prepended to them.
- All parameters in a routine are mangled using the type of the parameter (in uppercase) prepended by the $ character. This is done in left to right order for each parameter of the routine.
- Objects and classes use special mangling : The class type or object type is given in the mangled name; The mangled name is as follows: _$$_TYPEDECL_$$ optionally preceded by mangled name of the unit and finishing with the method name.

The following constructs

    unit testman;

    interface
    type
      myobject = object
       constructor init;
       procedure mymethod;
      end;

    implementation

      constructor myobject.init;
      begin
      end;

      procedure myobject.mymethod;
      begin
      end;

      function myfunc: pointer;
      begin
      end;

      procedure myprocedure(var x: integer; y: longint; z : pchar);
      begin
      end;

    end.

will result in the following assembler file for the Intel 80x86 target:

    	.file "testman.pas"

    .text
    	.balign 16
    .globl	_TESTMAN$$_$$_MYOBJECT_$$_INIT
    _TESTMAN$$_$$_MYOBJECT_$$_INIT:
    	pushl	%ebp
    	movl	%esp,%ebp
    	subl	$4,%esp
    	movl	$0,%edi
    	call	FPC_HELP_CONSTRUCTOR
    	jz	.L5
    	jmp	.L7
    .L5:
    	movl	12(%ebp),%esi
    	movl	$0,%edi
    	call	FPC_HELP_FAIL
    .L7:
    	movl	%esi,%eax
    	testl	%esi,%esi
    	leave
    	ret	$8
    	.balign 16
    .globl	_TESTMAN$$_$$_MYOBJECT_$$_MYMETHOD
    _TESTMAN$$_$$_MYOBJECT_$$_MYMETHOD:
    	pushl	%ebp
    	movl	%esp,%ebp
    	leave
    	ret	$4
    	.balign 16
    _TESTMAN$$_MYFUNC:
    	pushl	%ebp
    	movl	%esp,%ebp
    	subl	$4,%esp
    	movl	-4(%ebp),%eax
    	leave
    	ret
    	.balign 16
    _TESTMAN$$_MYPROCEDURE$INTEGER$LONGINT$PCHAR:
    	pushl	%ebp
    	movl	%esp,%ebp
    	leave
    	ret	$12

## 3 Modifying the mangled names

To make the symbols externally accessible, it is possible to give nicknames to mangled names, or to change the mangled name directly. Two modifiers can be used:

cdecl:
  A function that has a `cdecl` modifier, will be used with C calling conventions, that is, the caller clears the stack. Also the mangled name will be the name exactly as it is declared. `cdecl` is part of the function declaration, and hence must be present both in the interface and implementation section of a unit.

alias:
  The `alias` modifier can be used to assign a second assembler label to your function. This label has the same name as the alias name you declared. This doesn't modify the calling conventions of the function. In other words, the `alias` modifier allows you to specify another name (a nickname) for your function or procedure.

  The prototype for an aliased function or procedure is as follows:

      Procedure AliasedProc; alias : 'AliasName';

  The procedure `AliasedProc` will also be known as `AliasName`. Take care, the name you specify is case sensitive (as C is).

Furthermore, the `exports` section of a library is also used to declare the names that will be exported by the shared library. The names in the exports section are case-sensitive (while the actual declaration of the routine is not). For more information on the creating shared libraries, chapter libraries.

#
3 Calling mechanism

Procedures and Functions are called with their parameters on the stack. Contrary to Turbo Pascal, all parameters are pushed on the stack, and they are pushed right to left, instead of left to right for Turbo Pascal. This is especially important if you have some assembly subroutines in Turbo Pascal which you would like to translate to Free Pascal.

Function results are returned in the accumulator, if they fit in the register. Methods calls (from either objects or clases) have an additional invisible parameter which is `self`. This parameter is the leftmost parameter within a method call (it is therefore the last parameter passed to the method).

When the procedure or function exits, it clears the stack.

Other calling methods are available for linking with external object files and libraries, these are summarized in table (CallingTable) . The first column lists the modifier you specify for a procedure declaration. The second one lists the order the paramaters are pushed on the stack. The third column specifies who is responsible for cleaning the stack: the caller or the called function. The alignment column indicates the alignment of the parameters sent to the stack area. Finally, the fifth column indicates if any registers are saved in the entry code of the subroutine.

Table: Calling mechanisms in Free Pascal
Modifier | Pushing order | Stack cleaned by | alignment | registers saved
<none> | Right-to-left | Function | default | None
cdecl | Right-to-left | Caller | GCC alignment | GCC registers
interrupt | Right-to-left | Function | default | all registers
pascal | Left-to-right | Function | default | None
safecall | Right-to-left | Function | default | GCC registers
stdcall | Right-to-left | Function | GCC alignment | GCC registers
popstack | Right-to-left | Caller | default | None
register | Left-to-right | Caller | default | None

More about this can be found in chapter Linking on linking. Information on GCC registers saved, GCC stack alignment and general stack alignment on an operating system basis can be found in Appendix . The `register` modifier is currently not supported, and maps to the default calling convention.

Furthermore, the `saveregisters` modifier can be used with any of the calling mechanism specifiers. When `saveregisters` is used, all registers will be saved on entry to the routine, and will be restored upon exit. Of course, if the routine is a function, and it normally returns its retun value in a register, that register will not be saved. Also, if the self register is used, it will also neither be saved nor restored.

#
4 Nested procedure and functions

When a routine is declared within the scope of a procedure or function, it is said to be nested. In this case, an additional invisible parameter is passed to the nested routine. This additional parameter is the frame pointer address of the calling routine. This permits the nested routine to access the local variables and parameters of the calling routine.

The resulting stack frame after the entry code of a simple nested procedure has been executed is shown in table (NestedStackFrame32) .

Table: Stack frame when calling a nested procedure (32-bit processors)
Offset from frame pointer | What is stored
+x | parameters
+8 | Frame pointer of parent routine
+4 | Return address
+0 | Saved frame pointer

#
5 Constructor and Destructor calls

When using objects that need virtual methods, the compiler uses two help procedures that are in the run-time library. They are called `FPC_HELP_DESTRUCTOR` and `FPC_HELP_CONSTRUCTOR`. They are used to allocate the necessary memory if needed, and to insert the Virtual Method Table (VMT) pointer in the newly allocated object.

When the compiler encounters a call to an object's constructor, it sets up the stack frame for the call, and inserts a call to the `FPC_HELP_CONSTRUCTOR` procedure before issuing the call to the real constructor. The helper procedure allocates the needed memory (if needed) and inserts the VMT pointer in the object. After that, the real constructor is called.

A call to `FPC_HELP_DESTRUCTOR` is inserted in every destructor declaration, just before the destructor's exit sequence, it deallocates the memory allocated in the constructor.

# 6 Entry and exit code

Each Pascal procedure and function begins and ends with standard epilogue and prologue code.

## 1 Intel 80x86 standard routine prologue / epilogue

Standard entry code for procedures and functions is as follows on the 80x86 architecture:

       pushl   %ebp
       movl    %esp,%ebp

The generated exit sequence for procedure and functions looks as follows:

       leave
       ret  $xx

Where `xx` is the total size of the pushed parameters.

To have more information on function return values take a look at section RegConvs.

## 2 Motorola 680x0 standard routine prologue / epilogue

Standard entry code for procedures and functions is as follows on the 680x0 architecture:

       move.l  a6,-(sp)
       move.l  sp,a6

The generated exit sequence for procedure and functions looks as follows:

       unlk   a6
       move.l (sp)+,a0     ; Get return address
       add.l  #xx,sp       ; Remove allocated stack
       move.l a0,-(sp)     ; Put back return address on top of the stack

Where `xx` is the total size of the pushed parameters.

To have more information on function return values take a look at section RegConvs.

#
7 Parameter passing

When a function or procedure is called, then the following is done by the compiler:

1. If there are any parameters to be passed to the procedure, they are pushed from right to left on the stack.
2. If a function is called that returns a variable of type `String`, `Set`, `Record`, `Object` or `Array`, then an address to store the function result in, is pushed on the stack.
3. If the called procedure or function is an object method, then the pointer to `self` is pushed on the stack.
4. If the procedure or function is nested in another function or procedure, then the frame pointer of the parent procedure is pushed on the stack.
5. The return address is pushed on the stack (This is done automatically by the instruction which calls the subroutine).

The resulting stack frame upon entering looks as in table (StackFrame) .

Table: Stack frame when calling a procedure (32-bit model)
Offset | What is stored | Optional?
+x | parameters | Yes
+12 | function result | Yes
+8 | self | Yes
+4 | Return address | No
+0 | Frame pointer of parent procedure | Yes

## 1 Parameter alignment

Each parameter passed to a routine is guaranteed to decrement the stack pointer by a certain minimum amount. This behavior varies from one operating system to another. For example, passing a byte as a value parameter to a routine could either decrement the stack pointer by 1, 2, 4 or even 8 bytes depending on the target operating system and processor. The minimal default stack pointer decrement value is given in Appendix .

For example, on FREEBSD, all parameters passed to a routine guarantee a minimal stack decrease of four bytes per parameter, even if the parameter actually takes less then 4 bytes to store on the stack (such as passing a byte value parameter to the stack).

## 2 Processor limitations

Certain processors have limitations on the size of the parameters which can be passed to routine. This is shown in table (CPUStackLimits) .

Table: Maximum parameter sizes for processors
Processor | Limit (in Bytes)
Intel 80x86 | 64K
Motorola 680x0 | 32K