home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-12-19 | 182.8 KB | 5,563 lines |
- Free Pascal
- Programmers' manual
-
- Programmers' manual for Free Pascal, version 0.99.12
- 1.6
- July 1999
-
-
-
-
-
-
-
-
-
- Micha¿el Van Canneyt
-
-
-
- Contents
-
- 1 Compiler directives 9
- 1.1 Local directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
- $A or $ALIGN: Align Data . . . . . . . . . . . . . . . . . . . . . . . . 9
- $ASMMODE : Assembler mode . . . . . . . . . . . . . . . . . . . . . . . 9
- $B or $BOOLEVAL: Complete boolean evaluation . . . . . . . . . . . . 10
- $C or $ASSERTIONS : Assertion support . . . . . . . . . . . . . . . . . 10
- $DEFINE : Define a symbol . . . . . . . . . . . . . . . . . . . . . . . . 10
- $ELSE : Switch conditional compilation . . . . . . . . . . . . . . . . . 11
- $ENDIF : End conditional compilation . . . . . . . . . . . . . . . . . 11
- $ERROR : Generate error message . . . . . . . . . . . . . . . . . . . . 11
- $F : Far or near functions . . . . . . . . . . . . . . . . . . . . . . . . 11
- $FATAL : Generate fatal error message . . . . . . . . . . . . . . . . . 12
- $GOTO : Support Goto and Label . . . . . . . . . . . . . . . . . . . . 12
- $H or $LONGSTRINGS : Use AnsiStrings . . . . . . . . . . . . . . . . . 13
- $HINT : Generate hint message . . . . . . . . . . . . . . . . . . . . . 13
- $HINTS : Emit hints . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
- $IF : Start conditional compilation . . . . . . . . . . . . . . . . . . . 13
- $IFDEF : Start conditional compilation . . . . . . . . . . . . . . . . . 13
- $IFNDEF : Start conditional compilation . . . . . . . . . . . . . . . . 13
- $IFOPT : Start conditional compilation . . . . . . . . . . . . . . . . . 13
- $INFO : Generate info message . . . . . . . . . . . . . . . . . . . . . 14
- $INLINE : Allow inline code. . . . . . . . . . . . . . . . . . . . . . . . 14
- $I or $IOCHECKS : Input/Output checking . . . . . . . . . . . . . . . 14
- $I or $INCLUDE : Include file . . . . . . . . . . . . . . . . . . . . . . 15
- $I or $INCLUDE : Include compiler info . . . . . . . . . . . . . . . . . 15
- $I386 XXX : Specify assembler format . . . . . . . . . . . . . . . . . 16
- $L or $LINK : Link object file . . . . . . . . . . . . . . . . . . . . . . 16
- $LINKLIB : Link to a library . . . . . . . . . . . . . . . . . . . . . . . 16
- $M or $TYPEINFO : Generate type info . . . . . . . . . . . . . . . . . 17
- $MACRO : Allow use of macros. . . . . . . . . . . . . . . . . . . . . . . 17
-
-
-
- 1
-
-
-
- CONTENTS CONTENTS
-
-
- $MESSAGE : Generate info message . . . . . . . . . . . . . . . . . . . 17
- $MMX : Intel MMX support . . . . . . . . . . . . . . . . . . . . . . . . 17
- $NOTE : Generate note message . . . . . . . . . . . . . . . . . . . . . 18
- $NOTES : Emit notes . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
- $OUTPUT FORMAT : Specify the output format . . . . . . . . . . . . . 19
- $P or $OPENSTRINGS : Use open strings . . . . . . . . . . . . . . . . . 19
- $PACKENUM : Minimum enumeration type size . . . . . . . . . . . . . 19
- $PACKRECORDS : Alignment of record elements . . . . . . . . . . . . . 19
- $Q $OVERFLOWCHECKS: Overflow checking . . . . . . . . . . . . . . . . 20
- $R or $RANGECHECKS : Range checking . . . . . . . . . . . . . . . . . 20
- $SATURATION : Saturation operations . . . . . . . . . . . . . . . . . . 20
- $SMARTLINK : Use smartlinking . . . . . . . . . . . . . . . . . . . . . 20
- $STATIC : Allow use of Static keyword. . . . . . . . . . . . . . . . . 21
- $STOP : Generate fatal error message . . . . . . . . . . . . . . . . . . 21
- $T or $TYPEDADDRESS : Typed address operator (@) . . . . . . . . . 21
- $UNDEF : Undefine a symbol . . . . . . . . . . . . . . . . . . . . . . . 21
- $V or $VARSTRINGCHECKS : Var-string checking . . . . . . . . . . . . 22
- $WAIT : Wait for enter key press . . . . . . . . . . . . . . . . . . . . . 22
- $WARNING : Generate warning message . . . . . . . . . . . . . . . . . 22
- $WARNINGS : Emit warnings . . . . . . . . . . . . . . . . . . . . . . . 22
- $X or $EXTENDEDSYNTAX : Extended syntax . . . . . . . . . . . . . . 22
- 1.2 Global directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
- $APPTYPE : Specify type of application (Win32 only) . . . . . . . . . 23
- $D or $DEBUGINFO: Debugging symbols . . . . . . . . . . . . . . . . . 23
- $DESCRIPTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
- $E : Emulation of coprocessor . . . . . . . . . . . . . . . . . . . . . . 23
- $G : Generate 80286 code . . . . . . . . . . . . . . . . . . . . . . . . 24
- $INCLUDEPATH : Specify include path. . . . . . . . . . . . . . . . . . 24
- $L or $LOCALSYMBOLS: Local symbol information . . . . . . . . . . . 24
- $LIBRARYPATH : Specify library path. . . . . . . . . . . . . . . . . . . 25
- $M or $MEMORY: Memory sizes . . . . . . . . . . . . . . . . . . . . . . 25
- $MODE : Set compiler compatibility mode . . . . . . . . . . . . . . . . 25
- $N : Numeric processing . . . . . . . . . . . . . . . . . . . . . . . . . 26
- $O : Overlay code generation . . . . . . . . . . . . . . . . . . . . . . 26
- $OBJECTPATH : Specify object path. . . . . . . . . . . . . . . . . . . . 26
- $S : Stack checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
- $UNITPATH : Specify unit path. . . . . . . . . . . . . . . . . . . . . . 26
- $W or $STACKFRAMES : Generate stackframes . . . . . . . . . . . . . . 27
- $Y or $REFERENCEINFO : Insert Browser information . . . . . . . . . 27
-
-
-
- 2
-
-
-
- CONTENTS CONTENTS
-
-
- 2 Using conditionals, messages and macros 28
- 2.1 Conditionals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
- 2.2 Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
- 2.3 Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
-
- 3 Using Assembly language 35
- 3.1 Intel syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
- 3.2 AT&T Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
- 3.3 Calling mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
- Ix86 calling conventions . . . . . . . . . . . . . . . . . . . . . . . . 40
- M680x0 calling conventions . . . . . . . . . . . . . . . . . . . . . . 41
- 3.4 Signalling changed registers . . . . . . . . . . . . . . . . . . . . . . . 41
- 3.5 Register Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
- Intel x86 version . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
- Motorola 680x0 version . . . . . . . . . . . . . . . . . . . . . . . . . 42
-
- 4 Linking issues 43
- 4.1 Using external functions or procedures . . . . . . . . . . . . . . . . . 43
- 4.2 Using external variables . . . . . . . . . . . . . . . . . . . . . . . . . 45
- 4.3 Linking to an object file . . . . . . . . . . . . . . . . . . . . . . . . . 46
- 4.4 Linking to a library . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
- 4.5 Making libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
- Exporting functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
- Exporting variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
- Compiling libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
- Moving units into a library . . . . . . . . . . . . . . . . . . . . . . . 50
- Unit searching strategy . . . . . . . . . . . . . . . . . . . . . . . . . 50
- 4.6 Using smart linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
-
- 5 Objects 52
- 5.1 Constructor and Destructor calls . . . . . . . . . . . . . . . . . . . . 52
- 5.2 Memory storage of objects . . . . . . . . . . . . . . . . . . . . . . . . 52
- 5.3 The Virtual Method Table . . . . . . . . . . . . . . . . . . . . . . . . 52
-
- 6 Generated code 54
- 6.1 Units . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
- 6.2 Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
-
- 7 Intel MMX support 56
- 7.1 What is it about ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
- 7.2 Saturation support . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
- 7.3 Restrictions of MMX support . . . . . . . . . . . . . . . . . . . . . . 57
-
-
- 3
-
-
-
- CONTENTS CONTENTS
-
-
- 7.4 Supported MMX operations . . . . . . . . . . . . . . . . . . . . . . . 58
- 7.5 Optimizing MMX support . . . . . . . . . . . . . . . . . . . . . . . . 58
-
- 8 Memory issues 59
- 8.1 The 32-bit model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
- 8.2 The stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
- Intel x86 version . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
- Motorola 680x0 version . . . . . . . . . . . . . . . . . . . . . . . . . 61
- 8.3 The heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
- The heap grows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
- Using Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
- Using the split heap . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
- 8.4 Using dos memory under the Go32 extender . . . . . . . . . . . . . 63
-
- 9 Optimizations 65
- 9.1 Non processor specific . . . . . . . . . . . . . . . . . . . . . . . . . 65
- Constant folding . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
- Constant merging . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
- Short cut evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . 65
- Constant set inlining . . . . . . . . . . . . . . . . . . . . . . . . . . 66
- Small sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
- Range checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
- Shifts instead of multiply or divide . . . . . . . . . . . . . . . . . . 66
- Automatic alignment . . . . . . . . . . . . . . . . . . . . . . . . . . 66
- Smart linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
- Inline routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
- Case optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
- Stack frame omission . . . . . . . . . . . . . . . . . . . . . . . . . . 67
- Register variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
- Intel x86 specific . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
- Motorola 680x0 specific . . . . . . . . . . . . . . . . . . . . . . . . 69
- 9.2 Optimization switches . . . . . . . . . . . . . . . . . . . . . . . . . . 69
- 9.3 Tips to get faster code . . . . . . . . . . . . . . . . . . . . . . . . . . 70
- 9.4 Floating point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
- Intel x86 specific . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
- Motorola 680x0 specific . . . . . . . . . . . . . . . . . . . . . . . . 71
-
- A Anatomy of a unit file 72
- A.1 Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
- A.2 reading ppufiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
- A.3 The Header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
-
-
- 4
-
-
-
- CONTENTS CONTENTS
-
-
- A.4 The sections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
- A.5 Creating ppufiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
-
- B Compiler and RTL source tree structure 77
- B.1 The compiler source tree . . . . . . . . . . . . . . . . . . . . . . . . . 77
- B.2 The RTL source tree . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
-
- C Compiler limits 79
-
- D Compiler modes 80
- D.1 FPC mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
- D.2 TP mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
- D.3 Delphi mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
- D.4 GPC mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
- D.5 OBJFPC mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
-
- E Using makefile.fpc 83
- E.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
- E.2 Programs needed to use the makefile . . . . . . . . . . . . . . . . . . 83
- E.3 Variables used by makefile.fpc . . . . . . . . . . . . . . . . . . . . . . 84
- Required variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
- Directory variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
- Target variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
- Compiler command-line variables . . . . . . . . . . . . . . . . . . . . 85
- E.4 Variables set by makefile.fpc . . . . . . . . . . . . . . . . . . . . . . . 86
- Directory variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
- Program names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
- File extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
- Target files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
- E.5 Rules and targets created by makefile.fpc . . . . . . . . . . . . . . . . 89
- Pattern rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
- Build rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
- Cleaning rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
- archiving rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
- Informative rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
- E.6 Using the provided template . . . . . . . . . . . . . . . . . . . . . . . 90
-
- F Compiling the compiler yourself 92
- F.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
- F.2 Before you begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
- F.3 Compiling using make . . . . . . . . . . . . . . . . . . . . . . . . . . 93
- F.4 Compiling by hand . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
-
-
- 5
-
-
-
- CONTENTS CONTENTS
-
-
- Compiling the RTL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
- Compiling the compiler . . . . . . . . . . . . . . . . . . . . . . . . . 95
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 6
-
-
-
- List of Tables
-
- 1.1 Formats generated by the x86 compiler . . . . . . . . . . . . . . . . . 19
-
- 2.1 Symbols defined by the compiler. . . . . . . . . . . . . . . . . . . . . 29
- 2.2 Predefined macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
-
- 3.1 Calling mechanisms in Free Pascal . . . . . . . . . . . . . . . . . . . 40
-
- 5.1 Object memory layout . . . . . . . . . . . . . . . . . . . . . . . . . . 53
- 5.2 Virtual Method Table memory layout . . . . . . . . . . . . . . . . . 53
-
- 8.1 Stack frame when calling a procedure . . . . . . . . . . . . . . . . . 60
-
- F.1 Possible defines when compiling FPC . . . . . . . . . . . . . . . . . . 96
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 7
-
-
-
- LIST OF TABLES LIST OF TABLES
-
-
- About this document
-
- This is the programmer's manual for Free Pascal.
- It describes some of the peculiarities of the Free Pascal compiler, and provides
- a glimpse of how the compiler generates its code, and how you can change the
- generated code. It will not, however, provide you with a detailed account of the
- inner workings of the compiler, nor will it tell you how to use the compiler (described
- in the Users' guide). It also will not describe the inner workings of the Run-Time
- Library (RTL). The best way to learn about the way the RTL is implemented is
- from the sources themselves.
- The things described here are useful if you want to do things which need greater
- flexibility than the standard Pascal language constructs. (described in the Reference
- guide)
- Since the compiler is continuously under development, this document may get out
- of date. Wherever possible, the information in this manual will be updated. If you
- find something which isn't correct, or you think something is missing, feel free to
- contact me1.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1at Michael.VanCanneyt@wisa.be
-
-
- 8
-
-
-
- Chapter 1
-
- Compiler directives
-
- Free Pascal supports compiler directives in your source file. They are not the same
- as Turbo Pascal directives, although some are supported for compatibility. There is
- a distinction between local and global directives; local directives take e ect from the
- moment they are encountered, global directives have an e ect on all of the compiled
- code.
- Many switches have a long form also. If they do, then the name of the long form
- is given also. For long switches, the + or - character to switch the option on or o ,
- may be replaced by ON or OFF keywords.
- Thus {$I+} is equivalent to {$IOCHECKS ON} or {$IOCHECKS +} and {$C-} is equiv-
- alent to {$ASSERTIONS OFF} or {$ASSERTIONS -}
- The long forms of the switches are the same as their Delphi counterparts.
-
-
- 1.1 Local directives
-
- Local directives can occur more than once in a unit or program, If they have a
- command-line counterpart, the command-line artgument is restored as the default
- for each compiled file. The local directives influence the compiler's behaviour from
- the moment they're encountered until the moment another switch annihilates their
- behaviour, or the end of the current unit or program is reached.
-
-
- $A or $ALIGN: Align Data
- This switch is recognized for Turbo Pascal Compatibility, but is not yet imple-
- mented. The alignment of data will be di erent in any case, since Free Pascal is a
- 32-bit compiler.
-
-
- $ASMMODE : Assembler mode
- The {$ASMMODE XXX directive informs the compiler what kind of assembler it can
- expect in an asm block. The XXX should be replaced by one of the following:
-
- att Indicates that asm blocks contain AT&T syntax assembler.
-
- intel Indicates that asm blocks contain Intel syntax assembler.
-
-
- 9
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- direct Tells the compiler that asm blocks should be copied directly to the assem-
- bler file.
-
- These switches are local, and retain their value to the end of the unit that is
- compiled, unless they are replaced by another directive of the same type. The
- command-line switch that corresponds to this switch is -R.
-
-
- $B or $BOOLEVAL: Complete boolean evaluation
- This switch is understood by the Free Pascal compiler, but is ignored. The com-
- piler always uses shortcut evaluation, i.e. the evaluation of a boolean expression is
- stopped once the result of the total exression is known with certainty.
- So, in the following example, the function Bofu, which has a boolean result, will
- never get called.
-
- If False and Bofu then
- ...
-
-
- $C or $ASSERTIONS : Assertion support
- The {$ASSERTION} switch determines if assert statements are compiled into the
- binary or not. If the switch is on, the statement
-
- Assert(BooleanExpression,AssertMessage);
-
- Will be compiled in the binary. If te BooleanExpression evaluates to False, the
- RTL will check if the AssertErrorProc is set. If it is set, it will be called with as
- parameters the AssertMessage message, the name of the file, the LineNumber and
- the address. If it is not set, a runtime error 227 is generated.
- The AssertErrorProc is defined as
-
- Type
- TAssertErrorProc=procedure(const msg,fname:string;lineno,erroraddr:longint);
- VarAssertErrorProc = TAssertErrorProc;
- This can be used mainly for debugging purposes. The SYSTEM unit sets the
- AssertErrorProc to a handler that displays a message on stderr and simply exits.
- The SYSUTILS unit catches the run-time error 227 and raises an EAssertionFailed
- exception.
-
-
- $DEFINE : Define a symbol
- The directive
-
- {$DEFINE name}
-
- defines the symbol name. This symbol remains defined until the end of the current
- module (i.e. unit or program), or until a $UNDEF name directive is encountered.
- If name is already defined, this has no e ect. Name is case insensitive.
-
-
-
- 10
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- $ELSE : Switch conditional compilation
- The {$ELSE } switches between compiling and ignoring the source text delimited by
- the preceding {$IFxxx} and following {$ENDIF}. Any text after the ELSE keyword
- but before the brace is ignored:
-
- {$ELSE some ignored text}
-
- is the same as
-
- {$ELSE}
-
- This is useful for indication what switch is meant.
-
-
- $ENDIF : End conditional compilation
- The {$ENDIF} directive ends the conditional compilation initiated by the last {$IFxxx}
- directive. Any text after the ENDIF keyword but before the closing brace is ignored:
-
- {$ENDIF some ignored text}
-
- is the same as
-
- {$ENDIF}
-
- This is useful for indication what switch is meant to be ended.
-
-
- $ERROR : Generate error message
- The following code
-
- {$ERROR This code is erroneous !}
-
- will display an error message when the compiler encounters it, and increase the
- error count of the compiler. The compiler will continue to compile, but no code will
- be emitted.
-
-
- $F : Far or near functions
- This directive is recognized for compatibility with Turbo Pascal. Under the 32-bit
- programming model, the concept of near and far calls have no meaning, hence the
- directive is ignored. A warning is printed to the screen, telling you so.
- As an example, : the following piece of code :
-
- {$F+}
-
- Procedure TestProc;
-
- begin
- Writeln ('Hello From TestProc');
- end;
-
- begin
- testProc
- end.
-
- 11
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- Generates the following compiler output:
-
- malpertuus: >pp -vw testf
- Compiler: ppc386
- Units are searched in: /home/michael;/usr/bin/;/usr/lib/ppc/0.9.1/linuxunits
- Target OS: Linux
- Compiling testf.pp
- testf.pp(1) Warning: illegal compiler switch
- 7739 kB free
- Calling assembler...
- Assembled...
- Calling linker...
- 12 lines compiled,
- 1.00000000000000E+0000
-
- You can see that the verbosity level was set to display warnings.
- If you declare a function as Far (this has the same e ect as setting it between
- {$F+}...{$F-} directives), the compiler also generates a warning :
-
- testf.pp(3) Warning: FAR ignored
-
- The same story is true for procedures declared as Near. The warning displayed in
- that case is:
-
- testf.pp(3) Warning: NEAR ignored
-
-
- $FATAL : Generate fatal error message
- The following code
-
- {$FATAL This code is erroneous !}
-
- will display an error message when the compiler encounters it, and trigger and
- increase the error count of the compiler. The compiler will immediatly stop the
- compilation process.
-
-
- $GOTO : Support Goto and Label
- If {$GOTO ON} is specified, the compiler will support Goto statements and Label
- declarations. By default, $GOTO OFF is assumed. This directive corresponds to the
- -Sg command-line option.
- As an example, the following code can be compiled:
-
- {$GOTO ON}
-
- label Theend;
-
- begin
- If ParamCount=0 then
- GoTo TheEnd;
- Writeln ('You spcified command-line options');
- TheEnd:
- end.
-
- 12
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- $H or $LONGSTRINGS : Use AnsiStrings
- If {$LONGSTRINGS ON} is specified, the keyword String (no length specifier) will
- be treated as AnsiString, and the compiler will treat the corresponding varible as
- an ansistring, and will generate corresponding code.
- By default, the use of ansistrings is o , corresponding to {$H-}.
- This feature is still experimental, and should be used with caution for the time
- being.
-
-
- $HINT : Generate hint message
- If the generation of hints is turned on, through the -vh command-line option or the
- {$HINTS ON} directive, then
-
- {$Hint This code should be optimized }
-
- will display a hint message when the compiler encounters it.
-
-
- $HINTS : Emit hints
- {$HINTS ON} switches the generation of hints on. {$HINTS OFF} switches the gen-
- eration of hints o . Contrary to the command-line option -vh this is a local switch,
- this is useful for checking parts of your code.
-
-
- $IF : Start conditional compilation
- The directive {$IF expr} will continue the compilation if the boolean expression
- expr evaluates to true. If the compilation evaluates to false, then the source are
- skipped to the first {$ELSE} or {$ENDIF} directive.
- The compiler must be able to evaluate the expression at compile time. This means
- that you cannot use variables or constants that are defined in the source. Macros
- and symbols may be used, however.
- More information on this can be found in the section about conditionals.
-
-
- $IFDEF : Start conditional compilation
- The {$IFDEF name} will skip the compilation of the text that follows it if the symbol
- name is not defined. If it is defined, then compilation continues as if the directive
- wasn't there.
-
-
- $IFNDEF : Start conditional compilation
- The {$IFNDEF name} will skip the compilation of the text that follows it if the
- symbol name is defined. If it is not defined, then compilation continues as if the
- directive wasn't there.
-
-
- $IFOPT : Start conditional compilation
- The {$IFOPT switch} will compile the text that follows it if the switch switch is
- currently in the specified state. If it isn't in the specified state, then compilation
- continues after the corresponding {$ENDIF} directive.
-
- 13
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- As an example:
-
- {$IFOPT M+}
- Writeln ('Compiled with type information');
- {$ENDIF}
-
- Will compile the writeln statement if generation of type information is on.
- Remark: The {$IFOPT} directive accepts only short options, i.e. {$IFOPT TYPEINFO}
- will not be accepted.
-
-
- $INFO : Generate info message
- If the generation of info is turned on, through the -vi command-line option, then
-
- {$INFO This was coded on a rainy day by Bugs Bunny }
-
- will display an info message when the compiler encounters it.
-
-
- $INLINE : Allow inline code.
- The {$INLINE ON} directive tells the compiler that the Inline procedure modifier
- should be allowed. Procedures that are declared inline are copied to the places
- where they are called. This has the e ect that there is no actual procedure call, the
- code of the procedure iis just copied to where the procedure is needed. By default,
- Inline procedures are not allowed. You need to specify this directive if you want
- to use inlined code. This directive is equivalent to the command-line switch -Si.
- Inline code is NOT exported from a unit. This means that if you call an inline
- procedure from another unit, a normal procedure call will be performed. Only
- inside units, Inline procedures are really inline.
-
-
- $I or $IOCHECKS : Input/Output checking
- The {$I-} or {$IOCHECKS OFF} directive tells the compiler not to generate in-
- put/output checking code in your program. By default, the compiler does not
- generate this code, you must switch it on using the -Ci command-lne switch.
- If you compile using the -Ci compiler switch, the Free Pascal compiler inserts
- input/output checking code after every input/output call in your program. If an
- error occurred during input or output, then a run-time error will be generated. Use
- this switch if you wish to avoid this behavior. If you still want to check if something
- went wrong, you can use the IOResult function to see if everything went without
- problems.
- Conversely, {$I+} will turn error-checking back on, until another directive is en-
- countered which turns it o again.
- The most common use for this switch is to check if the opening of a file went without
- problems, as in the following piece of code:
-
- ...
- assign (f,'file.txt');
- {$I-}
- rewrite (f);
- {$I+}
-
- 14
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- if IOResult<>0 then
- begin
- Writeln ('Error opening file : "file.txt"');
- exit
- end;
- ...
-
-
- $I or $INCLUDE : Include file
- The {$I filename} or {$INCLUDE filename} directive tells the compiler to read
- further statements from the file filename. The statements read there will be in-
- serted as if they occurred in the current file.
- The compiler will append the .pp extension to the file if you don't specify an exten-
- sion yourself. Do not put the filename between quotes, as they will be regarded as
- part of the file's name.
- You can nest included files, but not infinitely deep. The number of files is restricted
- to the number of file descriptors available to the Free Pascal compiler.
- Contrary to Turbo Pascal, include files can cross blocks. I.e. you can start a block
- in one file (with a Begin keyword) and end it in another (with a End keyword).
- The smallest entity in an include file must be a token, i.e. an identifier, keyword or
- operator.
- The compiler will look for the file to include in the following places:
-
- 1. It will look in the path specified in the include file name.
-
- 2. It will look in the directory where the current source file is.
-
- 3. it will look in all directories specified in the include file search path.
-
- You can add directories to the include file search path with the -I command-line
- option.
-
-
- $I or $INCLUDE : Include compiler info
- In this form:
-
- {$INCLUDE %xxx%}
-
- where xxx is one of TIME, DATE, FPCVERSION or FPCTARGET, will generate a macro
- with the value of these things. If xxx is none of the above, then it is assumed to be
- the value of an environment variable. It's value will be fetched, and inserted in the
- code as if it were a string.
- For example, the following program
-
- Program InfoDemo;
-
- Const User = {$I %USER%};
-
- begin
- Write ('This program was compiled at ',{$I %TIME%});
- Writeln (' on ',{$I %DATE%});
- Writeln ('By ',User);
-
- 15
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- Writeln ('Compiler version : ',{$I %FPCVERSION%});
- Writeln ('Target CPU : ',{$I %FPCTARGET%});
- end.
-
- Creates the following output :
-
- This program was compiled at 17:40:18 on 1998/09/09
- By michael
- Compiler version : 0.99.7
- Target CPU : i386
-
-
- $I386 XXX : Specify assembler format
- This switch selects the assembler reader. {$I386 XXX} has the same e ect as
- {$ASMMODE XXX}, section 1.1, page 9
-
-
- $L or $LINK : Link object file
- The {$L filename} or {$LINK filename} directive tells the compiler that the file
- filename should be linked to your program.
- The compiler will look for this file in the following way:
-
- 1. It will look in the path specified in the object file name.
-
- 2. It will look in the directory where the current source file is.
-
- 3. it will look in all directories specified in the object file search path.
-
- You can add directories to the object file search path with the -Fo option.
- On linux systems, the name is case sensitive, and must be typed exactly as it
- appears on your system.
- Remark : Take care that the object file you're linking is in a format the linker
- understands. Which format this is, depends on the platform you're on. Typing ld
- on the command line gives a list of formats ld knows about.
- You can pass other files and options to the linker using the -k command-line option.
- You can specify more than one of these options, and they will be passed to the linker,
- in the order that you specified them on the command line, just before the names of
- the object files that must be linked.
-
-
- $LINKLIB : Link to a library
- The {$LINKLIB name} will link to a library name. This has the e ect of passing
- -lname to the linker.
- As an example, consider the following unit:
-
- unit getlen;
-
- interface
- {$LINKLIB c}
-
- function strlen (P : pchar) : longint;cdecl;
-
- 16
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
-
- implementation
-
- function strlen (P : pchar) : longint;cdecl;external;
-
- end.
-
- If one would issue the command
-
- ppc386 foo.pp
-
- where foo.pp has the above unit in its uses clause, then the compiler would link
- your program to the c library, by passing the linker the -lc option.
- The same e ect could be obtained by removing the linklib directive in the above
- unit, and specify -k-lc on the command-line:
-
- ppc386 -k-lc foo.pp
-
-
- $M or $TYPEINFO : Generate type info
- For classes that are compiled in the {$M+ } or {$TYPEINFO ON} state, the compiler
- will generate Run-Time Type Information (RTTI). All descendent objects of an
- object that was compiled in the {$M+} state will get RTTI information too, as well
- as any published classes. By default, no Run-Time Type Information is generated.
- The TPersistent object that is present in the FCL (Free Component Library)
- is generated in the {$M+} state. The generation of RTTI allows programmers to
- stream objects, and to access published properties of objects, without knowing the
- actual class of the object.
- The run-time type information is accessible through the TypInfo unit, which is part
- of the Free Pascal Run-Time Library.
-
-
- $MACRO : Allow use of macros.
- In the {$MACRO ON} state, the compiler allows you to use C-style (although not
- as elaborate) macros. Macros provide a means for simple text substitution. More
- information on using macros can be found in the section 2.3, page 33 section. This
- directive is equivalent to the command-line switch -Sm.
-
-
- $MESSAGE : Generate info message
- If the generation of info is turned on, through the -vi command-line option, then
-
- {$MESSAGE This was coded on a rainy day by Bugs Bunny }
-
- will display an info message when the compiler encounters it. The e ect is the same
- as the {$INFO} directive.
-
-
- $MMX : Intel MMX support
- As of version 0.9.8, Free Pascal supports optimization for the MMX Intel processor
- (see also 7).
-
-
- 17
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- This optimizes certain code parts for the MMX Intel processor, thus greatly im-
- proving speed. The speed is noticed mostly when moving large amounts of data.
- Things that change are
-
- * Data with a size that is a multiple of 8 bytes is moved using the movq assembler
- instruction, which moves 8 bytes at a time
-
- Remark that MMX support is NOT emulated on non-MMX systems, i.e. if the pro-
- cessor doesn't have the MMX extensions, you cannot use the MMX optimizations.
- When MMX support is on, you aren't allowed to do floating point arithmetic. You
- are allowed to move floating point data, but no arithmetic can be done. If you wish
- to do floating point math anyway, you must first switch of MMX support and clear
- the FPU using the emms function of the cpu unit.
- The following example will make this more clear:
-
- Program MMXDemo;
-
- uses cpu;
-
- vard1 : double;
- a : array[0..10000] of double;
- i : longint;
-
- begin
- d1:=1.0;
- {$mmx+}
- { floating point data is used, but we do _no_ arithmetic }
- for i:=0 to 10000 do
- a[i]:=d2; { this is done with 64 bit moves }
- {$mmx-}
- emms; { clear fpu }
- { now we can do floating point arithmetic }
- ....
- end.
-
- See, however, the chapter on MMX (7) for more information on this topic.
-
-
- $NOTE : Generate note message
- If the generation of notes is turned on, through the -vn command-line option or
- the {$NOTES ON} directive, then
-
- {$NOTE Ask Santa Claus to look at this code }
-
- will display a note message when the compiler encounters it.
-
-
- $NOTES : Emit notes
- {$NOTES ON} switches the generation of notes on. {$NOTES OFF} switches the gen-
- eration of notes o . Contrary to the command-line option -vn this is a local switch,
- this is useful for checking parts of your code.
-
-
- 18
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
-
- Table 1.1: Formats generated by the x86 compiler
-
- Switch value Generated format
- att AT&T assembler file.
- o Unix object file.
- obj OMF file.
- wasm assembler for the Watcom assembler.
-
-
- $OUTPUT FORMAT : Specify the output format
- {$OUTPUT FORMAT format} has the same functionality as the -A command-line op-
- tion : It tells the compiler what kind of object file must be generated. You can
- specify this switch only befor the Program or Unit clause in your source file. The
- di erent kinds of formats are shown in table (1.1).
-
-
- $P or $OPENSTRINGS : Use open strings
- $PACKENUM : Minimum enumeration type size
- This directive tells the compiler the minimum number of bytes it should use when
- storing enumerated types. It is of the following form:
-
- {$PACKENUM xxx}
- {$MINENUMSIZE xxx}
-
- Where the form with $MINENUMSIZE is for Delphi compatibility. xxx can be one of
- 1,2 or 4, or NORMAL or DEFAULT, corresponding to the default value of 4.
- As an alternative form one can use {$Z1}, {$Z2} {$Z4}. Contrary to Delphi, the
- default size is 4 bytes ({$Z4}).
- So the following code
-
- {$PACKENUM 1}
- Type
- Days = (monday, tuesday, wednesday, thursday, friday,
- saturday, sunday);
-
- will use 1 byte to store a variable of type Days, wheras it nomally would use 4 bytes.
- The above code is equivalent to
-
- {$Z1}
- Type
- Days = (monday, tuesday, wednesday, thursday, friday,
- saturday, sunday);
-
- Remark: Sets are always put in 32 bit or 32 bytes, this cannot be changed
-
-
- $PACKRECORDS : Alignment of record elements
- This directive controls the byte alignment of the elements in a record, object or
- class type definition.
- It is of the following form:
-
- 19
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- {$PACKRECORDS n}
-
- Where n is one of 1,2,4,16 or NORMAL or DEFAULT. This means that the elements of a
- record that have size greater than n will be aligned on n byte boundaries. Elements
- with size less than or equal to n will be aligned to a natural boundary, i.e. to a
- power of two that is equal to or larger than the element's size.
- The default alignment (which can be selected with DEFAULT) is 2, contrary to Turbo
- Pascal, where it is 1.
- More information on this and an example program can be found in the reference
- guide, in the section about record types.
- Remark: Sets are always put in 32 bit or 32 bytes, this cannot be changed
-
-
- $Q $OVERFLOWCHECKS: Overflow checking
- The {$Q+} or {$OVERFLOWCHECKS ON} directive turns on integer overflow checking.
- This means that the compiler inserts code to check for overflow when doing com-
- putations with integers. When an overflow occurs, the run-time library will print a
- message Overflow at xxx, and exit the program with exit code 215.
- Remark: Overflow checking behaviour is not the same as in Turbo Pascal since
- all arithmetic operations are done via 32-bit values. Furthermore, the Inc() and
- Dec() standard system procedures are checked for overflow in Free Pascal, while
- in Turbo Pascal they are not.
- Using the {$Q-} switch switches o the overflow checking code generation.
- The generation of overflow checking code can also be controlled using the -Co com-
- mand line compiler option (see Users' guide).
-
-
- $R or $RANGECHECKS : Range checking
- By default, the compiler doesn't generate code to check the ranges of array in-
- dices, enumeration types, subrange types, etc. Specifying the {$R+} switch tells
- the computer to generate code to check these indices. If, at run-time, an index or
- enumeration type is specified that is out of the declared range of the compiler, then
- a run-time error is generated, and the program exits with exit code 201.
- The {$RANGECHECKS OFF} switch tells the compiler not to generate range checking
- code. This may result in faulty program behaviour, but no run-time errors will be
- generated.
- Remark: Range checking for sets and enumerations are not yet fully implemented.
-
-
- $SATURATION : Saturation operations
- This works only on the intel compiler, and MMX support must be on ({$MMX +})
- for this to have any e ect. See the section on saturation support (section 7.2, page
- 57) for more information on the e ect of this directive.
-
-
- $SMARTLINK : Use smartlinking
- A unit that is compiled in the {$SMARTLINK ON} state will be compiled in such a
- way that it can be used for smartlinking. This means that the unit is chopped
- in logical pieces: each procedure is put in it's own object file, and all object files
-
-
- 20
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- are put together in a big archive. When using such a unit, only the pieces of code
- that you really need or call, will be linked in your program, thus reducing the
- size of your executable substantially. Beware that using smartlinked units slows
- down the compilation process, because a separate object file must be created for
- each procedure. If you have units with many functions and procedures, this can
- be a time consuming process, even more so if you use an external assembler (the
- assembler is called to assemble each procedure or function code block).
- The smartlinking directive should be specified before the unit declaration part:
-
- {$SMARTLINK ON}
-
- Unit MyUnit;
-
- Interface
- ...
-
- This directive is equivalent to the -Cx command-line switch.
-
-
- $STATIC : Allow use of Static keyword.
- If you specify the {$STATIC ON} directive, then Static methods are allowed for ob-
- jects. Static objects methods do not require a Self variable. They are equivalent
- to Class methods for classes. By default, Static methods are not allowed.
- This directive is equivalent to the -St command-line option.
-
-
- $STOP : Generate fatal error message
- The following code
-
- {$STOP This code is erroneous !}
-
- will display an error message when the compiler encounters it. The compiler will
- immediatly stop the compilation process.
- It has the same e ect as the {$FATAL} directive.
-
-
- $T or $TYPEDADDRESS : Typed address operator (@)
- In the {$T+} or {$TYPEDADDRESS ON} state the @ operator, when applied to a
- variable, returns a result of type ^T, if the type of the variable is T. In the {$T-}
- state, the result is always an untyped pointer, which is assignment compatible with
- all other pointer types.
-
-
- $UNDEF : Undefine a symbol
- The directive
-
- {$UNDEF name}
-
- un-defines the symbol name if it was previously defined. Name is case insensitive.
-
-
-
- 21
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.1. LOCAL DIRECTIVES
-
-
- $V or $VARSTRINGCHECKS : Var-string checking
- When in the + or ON state, the compiler checks that strings passed as parameters
- are of the same, identical, string type as the declared parameters of the procedure.
-
-
- $WAIT : Wait for enter key press
- If the compiler encounters a
-
- {$WAIT }
-
- directive, it will resume compiling only after the user has pressed the enter key.
- If the generation of info messages is turned on, then the compiler will display the
- follwing message:
-
- Press <return> to continue
-
- before waiting for a keypress. Careful ! This may interfere with automatic compi-
- lation processes. It should be used for debuggig purposes only.
-
-
- $WARNING : Generate warning message
- If the generation of warnings is turned on, through the -vw command-line option
- or the {$WARNINGS ON} directive, then
-
- {$WARNING This is dubious code }
-
- will display a warning message when the compiler encounters it.
-
-
- $WARNINGS : Emit warnings
- {$WARNINGS ON} switches the generation of warnings on. {$WARNINGS OFF} switches
- the generation of warnings o . Contrary to the command-line option -vw this is a
- local switch, this is useful for checking parts of your code.
-
-
- $X or $EXTENDEDSYNTAX : Extended syntax
- Extended syntax allows you to drop the result of a function. This means that you
- can use a function call as if it were a procedure. Standard this feature is on. You
- can switch it o using the {$X-} or {$EXTENDEDSYNTAX OFF}directive.
- The following, for instance, will not compile :
-
- function Func (var Arg : sometype) : longint;
- begin
- ... { declaration of Func }
- end;
-
- ...
-
- {$X-}
- Func (A);
-
-
- 22
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.2. GLOBAL DIRECTIVES
-
-
- The reason this construct is supported is that you may wish to call a function for
- certain side-e ects it has, but you don't need the function result. In this case you
- don't need to assign the function result, saving you an extra variable.
- The command-line compiler switch -Sa1 has the same e ect as the {$X+} directive.
-
-
- 1.2 Global directives
-
- Global directives a ect the whole of the compilation process. That is why they also
- have a command-line counterpart. The command-line counterpart is given for each
- of the directives.
-
-
- $APPTYPE : Specify type of application (Win32 only)
- The {$APPTYPE XXX} accepts one argument that can have two possible values : GUI
- or CONSOLE. It is used to tell the windows Operating system if an application is
- a console application or a graphical application. By default, a program compiled
- by Free Pascal is a console application. Running it will display a console window.
- Specifying the {$APPTYPE GUI} directive will mark the application as a graphical
- application; no console window will be opened when the application is run. If run
- from the command-line, the command prompt will be returned immediatly after
- the application was started.
- Care should be taken when compiling GUI applications; the Input and Output files
- are not available in a GUI application, and attempting to read from or write to
- them will result in a run-time error.
- It is possible to determine the application type of a windows application at runtime.
- The IsConsole constant, declared in the Win32 system unit as
-
- Const
- IsConsole : Boolean
-
- contains True if the application is a console application, False if the application is
- a GUI application.
-
-
- $D or $DEBUGINFO: Debugging symbols
- When this switch is on ({$DEBUGINFO ON}), the compiler inserts GNU debugging
- information in the executable. The e ect of this switch is the same as the command-
- line switch -g. By default, insertion of debugging information is o .
-
-
- $DESCRIPTION
- This switch is recognised for compatibility only, but is ignored completely by the
- compiler. At a later stage, this switch may be activated.
-
-
- $E : Emulation of coprocessor
- This directive controls the emulation of the coprocessor. There is no command-line
- counterpart for this directive.
-
-
-
- 23
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.2. GLOBAL DIRECTIVES
-
-
- Intel x86 version
-
- When this switch is enabled, all floating point instructions which are not supported
- by standard coprocessor emulators will give out a warning.
- The compiler itself doesn't do the emulation of the coprocessor.
- To use coprocessor emulation under dos go32v1 there is nothing special required,
- as it is handled automatically. (As of version 0.99.10, the go32v1 platform is no
- longer be supported)
- To use coprocessor emulation under dos go32v2 you must use the emu387 unit,
- which contains correct initialization code for the emulator.
- Under linux, the kernel takes care of the coprocessor support.
-
- Motorola 680x0 version
-
- When the switch is on, no floating point opcodes are emitted by the code generator.
- Instead, internal run-time library routines are called to do the necessary calcula-
- tions. In this case all real types are mapped to the single IEEE floating point
- type.
- Remark : By default, emulation is on. It is possible to intermix emulation code
- with real floating point opcodes, as long as the only type used is single or real.
-
-
- $G : Generate 80286 code
- This option is recognised for Turbo Pascal compatibility, but is ignored.
-
-
- $INCLUDEPATH : Specify include path.
- This option serves to specify the include path, where the compiler looks for include
- files. {$INCLUDEPATH XXX will add XXX to the include path. XXX can contain one or
- more paths, separated by semi-colons or colons.
- for example
-
- {$INCLUDEPATH ../inc;../i386}
-
- {$I strings.inc}
-
- Will add the directories ../inc and ../i386 to the include path of the compiler. The
- compiler will look for the file strings.inc in both these directories, and will include
- the first found file. This directive is equivalent to the -Fi command-line switch.
- Caution is in order when using this directive: If you distribute files, the places of
- the files may not be the same as on your machine; moreover, the directory structure
- may be di erent. In general it would be fair to say that you should avoid using
- absolute paths, instead use relative paths, as in the example above. Only use this
- directive if you are certain of the places where the files reside. If you are not sure,
- it is better practice to use makefiles and makefile variables.
-
-
- $L or $LOCALSYMBOLS: Local symbol information
- This switch (not to be confused with the {$L file} file linking directive) is recog-
- nised for Turbo Pascal compatibility, but is ignored. Generation of symbol infor-
-
- 24
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.2. GLOBAL DIRECTIVES
-
-
- mation is controlled by the $D switch.
-
-
- $LIBRARYPATH : Specify library path.
- This option serves to specify the library path, where the linker looks for static or
- dynamic libraries. {$LIBRARYPATH XXX} will add XXX to the library path. XXX can
- contain one or more paths, separated by semi-colons or colons.
- for example
-
- {$LIBRARYPATH /usr/X11/lib;/usr/local/lib}
-
- {$LINKLIB X11}
-
- Will add the directories /usr/X11/lib and /usr/local/lib to the linker library path.
- The linker will look for the library libX11.so in both these directories, and use the
- first found file. This directive is equivalent to the -Fl command-line switch.
- Caution is in order when using this directive: If you distribute files, the places of
- the libraries may not be the same as on your machine; moreover, the directory
- structure may be di erent. In general it would be fair to say that you should avoid
- using this directive. If you are not sure, it is better practice to use makefiles and
- makefile variables.
-
-
- $M or $MEMORY: Memory sizes
- This switch can be used to set the heap and stacksize. It's format is as follows:
-
- {$M StackSize,HeapSize}
-
- where StackSize and HeapSize should be two integer values, greater than 1024.
- The first number sets the size of the stack, and the second the size of the heap.
- (Stack setting is ignored under linux). The two numbers can be set on the com-
- mand line using the -Ch and -Cs switches.
-
-
- $MODE : Set compiler compatibility mode
- The {$MODE} sets the compatibility mode of the compiler. This is equivalent to
- setting one of the command-line options -So, -Sd, -Sp or -S2. it has the following
- arguments:
-
- Default Default mode. This reverts back to the mode that was set on the command-
- line.
- Delphi Delphi compatibility mode. All object-pascal extensions are enabled. This
- is the same as the command-line option -Sd.
- TP Turbo pascal compatibility mode. Object pascal extensions are disabled, ex-
- cept ansistrings, which remain valid. This is the same as the command-line
- option -So
- FPC FPC mode. This is the default, if no command-line switch is supplied.
- OBJFPC Object pascal mode. This is the same as the -S2 command-line option.
- GPC GNU pascal mode. This is the same as the -Sp command-line option.
-
- For an exact description of each of these modes, see appendix D, on page 80.
-
- 25
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.2. GLOBAL DIRECTIVES
-
-
- $N : Numeric processing
- This switch is recognised for Turbo Pascal compatibility, but is otherwise ignored,
- since the compiler always uses the coprocessor for floating point mathematics.
-
-
- $O : Overlay code generation
- This switch is recognised for Turbo Pascal compatibility, but is otherwise ignored.
-
-
- $OBJECTPATH : Specify object path.
- This option serves to specify the object path, where the compiler looks for object
- files. {$OBJECTPATH XXX will add XXX to the object path. XXX can contain one or
- more paths, separated by semi-colons or colons.
- for example
-
- {$OBJECTPATH ../inc;../i386}
-
- {$L strings.o}
-
- Will add the directories ../inc and ../i386 to the object path of the compiler. The
- compiler will look for the file strings.o in both these directories, and will link the
- first found file in the program. This directive is equivalent to the -Fo command-line
- switch.
- Caution is in order when using this directive: If you distribute files, the places of
- the files may not be the same as on your machine; moreover, the directory structure
- may be di erent. In general it would be fair to say that you should avoid using
- absolute paths, instead use relative paths, as in the example above. Only use this
- directive if you are certain of the places where the files reside. If you are not sure,
- it is better practice to use makefiles and makefile variables.
-
-
- $S : Stack checking
- The {$S+} directive tells the compiler to generate stack checking code. This gen-
- erates code to check if a stack overflow occurred, i.e. to see whether the stack has
- grown beyond its maximally allowed size. If the stack grows beyond the maximum
- size, then a run-time error is generated, and the program will exit with exit code
- 202.
- Specifying {$S-} will turn generation of stack-checking code o .
- The command-line compiler switch -Ct has the same e ect as the {$S+} directive.
-
-
- $UNITPATH : Specify unit path.
- This option serves to specify the unit path, where the compiler looks for unit files.
- {$UNITPATH XXX} will add XXX to the unit path. XXX can contain one or more paths,
- separated by semi-colons or colons.
- for example
-
- {$UNITPATH ../units;../i386/units}
-
- Uses strings;
-
- 26
-
-
-
- CHAPTER 1. COMPILER DIRECTIVES 1.2. GLOBAL DIRECTIVES
-
-
- Will add the directories ../units and ../i386/units to the unit path of the compiler.
- The compiler will look for the file strings.ppu in both these directories, and will
- link the first found file in the program. This directive is equivalent to the -Fu
- command-line switch.
- Caution is in order when using this directive: If you distribute files, the places of
- the files may not be the same as on your machine; moreover, the directory structure
- may be di erent. In general it would be fair to say that you should avoid using
- absolute paths, instead use relative paths, as in the example above. Only use this
- directive if you are certain of the places where the files reside. If you are not sure,
- it is better practice to use makefiles and makefile variables.
-
-
- $W or $STACKFRAMES : Generate stackframes
- The {$W} switch directove controls the generation of stackframes. In the on state
- ({$STACKFRAMES ON}), the compiler will generate a stackframe for every procedure
- or function.
- In the o state, the compiler will omit the generation of a stackframe if the following
- conditions are satisfied:
-
- * The procedure has no parameters.
-
- * The procedure has no local variables.
-
- * If the procedure is not an assembler procedure, it must not have a asm ...
- end; block.
-
- * it is not a constuctor or desctructor.
-
- If these conditions are satisfied, the stack frame will be omitted.
-
-
- $Y or $REFERENCEINFO : Insert Browser information
- This switch controls the generation of browser inforation. It is recognized for com-
- patibility with Turbo Pascal and Delphi only, as Browser information generation is
- not yet fully supported.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 27
-
-
-
- Chapter 2
-
- Using conditionals, messages
- and macros
-
- The Free Pascal compiler supports conditionals as in normal Turbo Pascal. It does,
- however, more than that. It allows you to make macros which can be used in your
- code, and it allows you to define messages or errors which will be displayed when
- compiling.
-
-
- 2.1 Conditionals
-
- The rules for using conditional symbols are the same as under Turbo Pascal. Defin-
- ing a symbol goes as follows:
-
- {$Define Symbol }
-
- From this point on in your code, the compiler knows the symbol Symbol. Symbols
- are, like the Pascal language, case insensitive.
- You can also define a symbol on the command line. the -dSymbol option defines
- the symbol Symbol. You can specify as many symbols on the command line as you
- want.
- Undefining an existing symbol is done in a similar way:
-
- {$Undef Symbol }
-
- If the symbol didn't exist yet, this doesn't do anything. If the symbol existed
- previously, the symbol will be erased, and will not be recognized any more in the
- code following the {$Undef ...} statement.
- You can also undefine symbols from the command line with the -u command-line
- switch..
- To compile code conditionally, depending on whether a symbol is defined or not,
- you can enclose the code in a {$ifdef Symbol} .. {$endif} pair. For instance the
- following code will never be compiled :
-
- {$Undef MySymbol}
- {$ifdef Mysymbol}
- DoSomething;
-
- 28
-
-
-
- CHAPTER 2. USING CONDITIONALS, MESSAGES AND MA
- 2.1. CROS
- CONDITIONALS
-
-
-
- Table 2.1: Symbols defined by the compiler.
-
- Free
- VERv
- VERv r
- VERv r p
- OS
-
-
- ...
- {$endif}
-
- Similarly, you can enclose your code in a {$Ifndef Symbol} .. {$endif} pair. Then
- the code between the pair will only be compiled when the used symbol doesn't exist.
- For example, in the following example, the call to the DoSomething will always be
- compiled:
-
- {$Undef MySymbol}
- {$ifndef Mysymbol}
- DoSomething;
- ...
- {$endif}
-
- You can combine the two alternatives in one structure, namely as follows
-
- {$ifdef Mysymbol}
- DoSomething;
- {$else}
- DoSomethingElse
- {$endif}
-
- In this example, if MySymbol exists, then the call to DoSomething will be compiled.
- If it doesn't exist, the call to DoSomethingElse is compiled.
- The Free Pascal compiler defines some symbols before starting to compile your
- program or unit. You can use these symbols to di erentiate between di erent
- versions of the compiler, and between di erent compilers. In table (2.1), a list of
- pre-defined symbols is given1. In that table, you should change v with the version
- number of the compiler you're using, r with the release number and p with the
- patch-number of the compiler. 'OS' needs to be changed by the type of operating
- system. Currently this can be one of DOS, GO32V2, LINUX, OS2, WIN32, MACOS, AMIGA
- or ATARI.
- The OS symbol is undefined if you specify a target that is di erent from the platform
- you're compiling on. The -TSomeOS option on the command line will define the
- SomeOS symbol, and will undefine the existing platform symbol2.
- As an example : Version 0.9.1 of the compiler, running on a Linux system, defines
- the following symbols before reading the command line arguments: FPC, VER0,
- VER0 9, VER0 9 1 and LINUX. Specifying -TOS2 on the command-line will undefine
- the LINUX symbol, and will define the OS2 symbol.
- Remark: Symbols, even when they're defined in the interface part of a unit, are
- not available outside that unit.
- 1Remark: The FPK symbol is still defined for compatibility with older versions.
- 2In versions prior to 0.9.4, this didn't happen, thus making Cross-compiling impossible.
-
-
- 29
-
-
-
- CHAPTER 2. USING CONDITIONALS, MESSAGES AND MA
- 2.1. CROS
- CONDITIONALS
-
-
- Except for the Turbo Pascal constructs, from version 0.9.8 and higher, the Free
- Pascal compiler also supports a stronger conditional compile mechanism: The {$If
- } construct.
- The prototype of this construct is as follows :
-
- {$If expr}
- CompileTheseLines;
- {$else}
- BetterCompileTheseLines;
- {$endif}
-
- In this directive expr is a Pascal expression which is evaluated using strings, unless
- both parts of a comparision can be evaluated as numbers, in which case they are
- evaluated using numbers3. If the complete expression evaluates to '0', then it is
- considered false and rejected. Otherwise it is considered true and accepted. This
- may have unexpected consequences :
-
- {$If 0}
-
- Will evaluate to False and be rejected, while
-
- {$If 00}
-
- Will evaluate to True.
- You can use any Pascal operator to construct your expression : =, <>, >, <, >=,
- <=, AND, NOT, OR and you can use round brackets to change the precedence of the
- operators.
- The following example shows you many of the possibilities:
-
- {$ifdef fpc}
-
- vary : longint;
- {$else fpc}
-
- varz : longint;
- {$endif fpc}
-
- varx : longint;
- begin
-
- {$if (fpc_version=0) and (fpc_release>6) and (fpc_patch>4)}
- {$info At least this is version 0.9.5}
- {$else}
- {$fatal Problem with version check}
- {$endif}
-
- {$define x:=1234}
- 3Otherwise {$If 8>54} would evaluate to True
-
-
- 30
-
-
-
- CHAPTER 2. USING CONDITIONALS, MESSAGES AND MA
- 2.1. CROS
- CONDITIONALS
-
-
- {$if x=1234}
- {$info x=1234}
- {$else}
- {$fatal x should be 1234}
- {$endif}
-
- {$if 12asdf and 12asdf}
- {$info $if 12asdf and 12asdf is ok}
- {$else}
- {$fatal $if 12asdf and 12asdf rejected}
- {$endif}
-
- {$if 0 or 1}
- {$info $if 0 or 1 is ok}
- {$else}
- {$fatal $if 0 or 1 rejected}
- {$endif}
-
- {$if 0}
- {$fatal $if 0 accepted}
- {$else}
- {$info $if 0 is ok}
- {$endif}
-
- {$if 12=12}
- {$info $if 12=12 is ok}
- {$else}
- {$fatal $if 12=12 rejected}
- {$endif}
-
- {$if 12<>312}
- {$info $if 12<>312 is ok}
- {$else}
- {$fatal $if 12<>312 rejected}
- {$endif}
-
-
- {$if 12<=312}
- {$info $if 12<=312 is ok}
- {$else}
- {$fatal $if 12<=312 rejected}
- {$endif}
-
- {$if 12<312}
- {$info $if 12<312 is ok}
- {$else}
- {$fatal $if 12<312 rejected}
- {$endif}
-
- {$if a12=a12}
- {$info $if a12=a12 is ok}
- {$else}
- {$fatal $if a12=a12 rejected}
- {$endif}
-
- 31
-
-
-
- CHAPTER 2. USING CONDITIONALS, MESSAGES AND MACR
- 2.2. OS
- MESSAGES
-
-
-
- {$if a12<=z312}
- {$info $if a12<=z312 is ok}
- {$else}
- {$fatal $if a12<=z312 rejected}
- {$endif}
-
-
- {$if a12<z312}
- {$info $if a12<z312 is ok}
- {$else}
- {$fatal $if a12<z312 rejected}
- {$endif}
-
- {$if not(0)}
- {$info $if not(0) is OK}
- {$else}
- {$fatal $if not(0) rejected}
- {$endif}
-
- {$info *************************************************}
- {$info * Now have to follow at least 2 error messages: *}
- {$info *************************************************}
-
- {$if not(0}
- {$endif}
-
- {$if not(<}
- {$endif}
-
- end.
-
- As you can see from the example, this construct isn't useful when used with normal
- symbols, but it is if you use macros, which are explained in section 2.3, page 33,
- they can be very useful. When trying this example, you must switch on macro
- support, with the -Sm command-line switch.
-
- 2.2 Messages
-
- Free Pascal lets you define normal, warning and error messages in your code. Mes-
- sages can be used to display useful information, such as copyright notices, a list of
- symbols that your code reacts on etc.
- Warnings can be used if you think some part of your code is still buggy, or if you
- think that a certain combination of symbols isn't useful. In general anything which
- may cause problems when compiling.
- Error messages can be useful if you need a certain symbol to be defined to warn that
- a certain variable isn't defined or so, or when the compiler version isn't suitable for
- your code.
- The compiler treats these messages as if they were generated by the compiler. This
- means that if you haven't turned on warning messages, the warning will not be
- displayed. Errors are always displayed, and the compiler stops if 50 errors have
- occurred. After a fatal error, the compiler stops at once.
-
- 32
-
-
-
- CHAPTER 2. USING CONDITIONALS, MESSAGES AND MACROS
- 2.3. MACROS
-
-
- For messages, the syntax is as follows :
-
- {$Message Message text }
-
- Or
-
- {$Info Message text }
-
- For notes:
-
- {$Note Message text }
-
- For warnings:
-
- {$Warning Warning Message text }
-
- For errors :
-
- {$Error Error Message text }
-
- Lastly, for fatal errors :
-
- {$Fatal Error Message text }
-
- or
-
- {$Stop Error Message text }
-
- The di erence between $Error and $FatalError or $Stop messages is that when
- the compiler encounters an error, it still continues to compile. With a fatal error,
- the compiler stops.
- Remark : You cannot use the '}' character in your message, since this will be treated
- as the closing brace of the message.
- As an example, the following piece of code will generate an error when the symbol
- RequiredVar isn't defined:
-
- {$ifndef RequiredVar}
- {$Error Requiredvar isn't defined !}
- {$endif}
-
- But the compiler will continue to compile. It will not, however, generate a unit file
- or a program (since an error occurred).
-
-
- 2.3 Macros
-
- Macros are very much like symbols in their syntax, the di erence is that macros
- have a value whereas a symbol simply is defined or is not defined. If you want macro
- support, you need to specify the -Sm command-line switch, otherwise your macro
- will be regarded as a symbol.
- Defining a macro in your program is done in the same way as defining a symbol; in
- a {$define } preprocessor statement4:
- 4In compiler versions older than 0.9.8, the assignment operator for a macros wasn't :=, but =
-
-
- 33
-
-
-
- CHAPTER 2. USING CONDITIONALS, MESSAGES AND MACROS
- 2.3. MACROS
-
-
-
- Table 2.2: Predefined macros
-
- Symbol Contains
- FPC VERSION The version number of the compiler.
- FPC RELEASE The release number of the compiler.
- FPC PATCH The patch number of the compiler.
-
-
- {$define ident:=expr}
-
- If the compiler encounters ident in the rest of the source file, it will be replaced
- immediately by expr. This replacement works recursive, meaning that when the
- compiler expanded one of your macros, it will look at the resulting expression again
- to see if another replacement can be made. You need to be careful with this, because
- an infinite loop can occur in this manner.
- Here are two examples which illustrate the use of macros:
-
- {$define sum:=a:=a+b;}
- ...
- sum { will be expanded to 'a:=a+b;'
- remark the absence of the semicolon}
- ...
- {$define b:=100}
- sum { Will be expanded recursively to a:=a+100; }
- ...
-
- The previous example could go wrong :
-
- {$define sum:=a:=a+b;}
- ...
- sum { will be expanded to 'a:=a+b;'
- remark the absence of the semicolon}
- ...
- {$define b=sum} { DON'T do this !!!}
- sum { Will be infinitely recursively expanded... }
- ...
-
- On my system, the last example results in a heap error, causing the compiler to
- exit with a run-time error 203.
- Remark: Macros defined in the interface part of a unit are not available outside
- that unit ! They can just be used as a notational convenience, or in conditional
- compiles.
- By default, from version 0.9.8 of the compiler on, the compiler predefines three
- macros, containing the version number, the release number and the patch number.
- They are listed in table (2.2).
- Remark: Don't forget that macros support isn't on by default. You need to compile
- with the -Sm command-line switch.
-
-
-
-
-
-
- 34
-
-
-
- Chapter 3
-
- Using Assembly language
-
- Free Pascal supports inserting of assembler instructions in your code. The mecha-
- nism for this is the same as under Turbo Pascal. There are, however some substan-
- tial di erences, as will be explained in the following.
-
-
- 3.1 Intel syntax
-
- As of version 0.9.7, Free Pascal supports Intel syntax for the Intel family of Ix86
- processors in it's asm blocks.
- The Intel syntax in your asm block is converted to AT&T syntax by the compiler,
- after which it is inserted in the compiled source. The supported assembler constructs
- are a subset of the normal assembly syntax. In what follows we specify what
- constructs are not supported in Free Pascal, but which exist in Turbo Pascal:
-
- * The TBYTE qualifier is not supported.
-
- * The & identifier override is not supported.
-
- * The HIGH operator is not supported.
-
- * The LOW operator is not supported.
-
- * The OFFSET and SEG operators are not supported. use LEA and the various
- Lxx instructions instead.
-
- * Expressions with constant strings are not allowed.
-
- * Access to record fields via parenthesis is not allowed
-
- * Typecasts with normal pascal types are not allowed, only recognized assembler
- typecasts are allowed.
- Example:
-
- mov al, byte ptr MyWord -- allowed,
- mov al, byte(MyWord) -- allowed,
- mov al, shortint(MyWord) -- not allowed.
-
- * Pascal type typecasts on constants are not allowed.
- Example:
-
-
- 35
-
-
-
- CHAPTER 3. USING ASSEMBLY LANGUAGE 3.1. INTEL SYNTAX
-
-
- const s= 10; const t = 32767;
-
- in Turbo Pascal:
-
- mov al, byte(s) -- useless typecast.
- mov al, byte(t) -- syntax error!
-
- In this parser, either of those cases will give out a syntax error.
-
- * Constant references expressions with constants only are not allowed (in all
- cases they do not work in protected mode, under linux i386).
- Examples:
-
- mov al,byte ptr ['c'] -- not allowed.
- mov al,byte ptr [100h] -- not allowed.
-
- (This is due to the limitation of Turbo Assembler).
-
- * Brackets within brackets are not allowed
-
- * Expressions with segment overrides fully in brackets are presently not sup-
- ported, but they can easily be implemented in BuildReference if requested.
- Example:
-
- mov al,[ds:bx] -- not allowed
-
- use instead:
-
- mov al,ds:[bx]
-
- * Possible allowed indexing are as follows:
-
- ¡ Sreg:[REG+REG*SCALING+/-disp]
- ¡ SReg:[REG+/-disp]
- ¡ SReg:[REG]
- ¡ SReg:[REG+REG+/-disp]
- ¡ SReg:[REG+REG*SCALING]
-
- Where Sreg is optional and specifies the segment override. Notes:
-
- 1. The order of terms is important contrary to Turbo Pascal.
- 2. The Scaling value must be a value, and not an identifier to a symbol.
- Examples:
- const myscale = 1;
- ...
- mov al,byte ptr [esi+ebx*myscale] -- not allowed.
- use:
- mov al, byte ptr [esi+ebx*1]
-
- * Possible variable identifier syntax is as follows: (Id = Variable or typed con-
- stant identifier.)
-
- 1. ID
- 2. [ID]
-
- 36
-
-
-
- CHAPTER 3. USING ASSEMBLY LANGUAGE 3.1. INTEL SYNTAX
-
-
- 3. [ID+expr]
- 4. ID[expr]
-
- Possible fields are as follow:
-
- 1. ID.subfield.subfield ...
- 2. [ref].ID.subfield.subfield ...
- 3. [ref].typename.subfield ...
-
- * Local Labels: Contrary to Turbo Pascal, local labels, must at least contain
- one character after the local symbol indicator.
- Example:
-
- @: -- not allowed
-
- use instead, for example:
-
- @1: -- allowed
-
- * Contrary to Turbo Pascal local references cannot be used as references, only
- as displacements.
- example:
-
- lds si,@mylabel -- not allowed
-
- * Contrary to Turbo Pascal, SEGCS, SEGDS, SEGES and SEGSS segment overrides
- are presently not supported. (This is a planned addition though).
-
- * Contrary to Turbo Pascal where memory sizes specifiers can be practically
- anywhere, the Free Pascal Intel inline assembler requires memory size speci-
- fiers to be outside the brackets.
- example:
-
- mov al,[byte ptr myvar] -- not allowed.
-
- use:
-
- mov al,byte ptr [myvar] -- allowed.
-
- * Base and Index registers must be 32-bit registers. (limitation of the GNU
- Assembler).
-
- * XLAT is equivalent to XLATB.
-
- * Only Single and Double FPU opcodes are supported.
-
- * Floating point opcodes are currently not supported (except those which in-
- volve only floating point registers).
-
- The Intel inline assembler supports the following macros :
-
- @Result represents the function result return value.
-
- Self represents the object method pointer in methods.
-
-
-
- 37
-
-
-
- CHAPTER 3. USING ASSEMBLY LANGUAGE 3.2. AT&T SYNTAX
-
-
- 3.2 AT&T Syntax
-
- Free Pascal uses the gnu as assembler to generate its object files for the Intel Ix86
- processors . Since the gnu assembler uses AT&T assembly syntax, the code you
- write should use the same syntax. The di erences between AT&T and Intel syntax
- as used in Turbo Pascal are summarized in the following:
-
- * The opcode names include the size of the operand. In general, one can say
- that the AT&T opcode name is the Intel opcode name, su xed with a 'l',
- 'w' or 'b' for, respectively, longint (32 bit), word (16 bit) and byte (8 bit)
- memory or register references. As an example, the Intel construct 'mov al bl
- is equivalent to the AT&T style 'movb %bl,%al' instruction.
-
- * AT&T immediate operands are designated with '$', while Intel syntax doesn't
- use a prefix for immediate operands. Thus the Intel construct 'mov ax, 2'
- becomes 'movb $2, %al' in AT&T syntax.
-
- * AT&T register names are preceded by a '%' sign. They are undelimited in
- Intel syntax.
-
- * AT&T indicates absolute jump/call operands with '*', Intel syntax doesn't
- delimit these addresses.
-
- * The order of the source and destination operands are switched. AT&T syntax
- uses 'Source, Dest', while Intel syntax features 'Dest, Source'. Thus the
- Intel construct 'add eax, 4' transforms to 'addl $4, %eax' in the AT&T
- dialect.
-
- * Immediate long jumps are prefixed with the 'l' prefix. Thus the Intel 'call/jmp
- section:offset' is transformed to 'lcall/ljmp $section,$offset'. Sim-
- ilarly the far return is 'lret', instead of the Intel 'ret far'.
-
- * Memory references are specified di erently in AT&T and Intel assembly. The
- Intel indirect memory reference
-
- Section:[Base + Index*Scale + Offs]
-
- is written in AT&T syntax as :
-
- Section:Offs(Base,Index,Scale)
-
- Where Base and Index are optional 32-bit base and index registers, and Scale
- is used to multiply Index. It can take the values 1,2,4 and 8. The Section is
- used to specify an optional section register for the memory operand.
-
- More information about the AT&T syntax can be found in the as manual, although
- the following di erences with normal AT&T assembly must be taken into account :
-
- * Only the following directives are presently supported:
-
- .byte
- .word
- .long
- .ascii
- .asciz
- .globl
-
- 38
-
-
-
- CHAPTER 3. USING ASSEMBLY LANGUAGE 3.3. CALLING MECHANISM
-
-
- * The following directives are recognized but are not supported:
-
- .align
- .lcomm
-
- Eventually they will be supported.
-
- * Directives are case sensitive, other identifiers are not case sensitive.
-
- * Contrary to GAS local labels/symbols must start with .L
-
- * The not operator '!' is not supported.
-
- * String expressions in operands are not supported.
-
- * CBTW,CWTL,CWTD and CLTD are not supported, use the normal intel
- equivalents instead.
-
- * Constant expressions which represent memory references are not allowed even
- though constant immediate value expressions are supported.
- examples:
-
- const myid = 10;
- ...
- movl $myid,%eax -- allowed
- movl myid(%esi),%eax -- not allowed.
-
- * When the .globl directive is found, the symbol following it is made public
- and is immediately emitted. Therefore label names with this name will be
- ignored.
-
- * Only Single and Double FPU opcodes are supported.
-
- The AT&T inline assembler supports the following macros :
-
- RESULT represents the function result return value.
-
- SELF represents the object method pointer in methods.
-
- OLDEBP represents the old base pointer in recusrive routines.
-
-
- 3.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.
- The registers are not saved when calling a function or procedure. If you want to
- call a procedure or function from assembly language, you must save any registers
- you wish to preserve.
- The first thing a procedure does is saving the base pointer, and setting the base
- pointer equal to the stack pointer. References to the pushed parameters and local
- variables are constructed using the base pointer.
-
- 39
-
-
-
- CHAPTER 3. USING ASSEMBLY LANGUAGE 3.3. CALLING MECHANISM
-
-
-
- Table 3.1: Calling mechanisms in Free Pascal
-
- Modifier Pushing order Stack cleaned by Parameters in registers
- (none) Right-to-left Function No
- cdecl Right-to-left Caller No
- export Right-to-left Caller No
- stdcall Right-to-left Function No
- popstack Right-to-left Caller No
-
-
- When the procedure or function exits, it clears the stack.
- When you want your code to be called by a C library or used in a C program,
- you will run into trouble because of this calling mechanism. In C, the calling
- procedure is expected to clear the stack, not the called procedure. In other words,
- the arguments still are on the stack when the procedure exits. To avoid this problem,
- Free Pascal supports the export modifier. Procedures that are defined using the
- export modifier, use a C-compatible calling mechanism. This means that they can
- be called from a C program or library, or that you can use them as a callback
- function.
- This also means that you cannot call this procedure or function from your own
- program, since your program uses the Pascal calling convention. However, in the
- exported function, you can of course call other Pascal routines.
- As of version 0.9.8, the Free Pascal compiler supports also the cdecl and stdcall
- modifiers, as found in Delphi. The cdecl modifier does the same as the export
- modifier, and stdcall does nothing, since Free Pascal pushes the paramaters from
- right to left by default. In addition to the Delphi cdecl construct, Free Pascal
- also supports the popstack directive; it is nearly the same a the cdecl directive,
- only it still mangles the name, i.e. makes it into a name such as the compiler uses
- internally.
- All this is summarized in table (3.1). 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. Finally, the last column specifies if registers
- are used to pass parameters to the function.
- More about this can be found in chapter 4, page 43 on linking.
-
-
- Ix86 calling conventions
- Standard entry code for procedures and functions is as follows on the x86 architec-
- ture:
-
- 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.
-
-
- 40
-
-
-
- CHAPTER 3. USING ASSEMBLY LANGUA
- 3.4. GE
- SIGNALLING CHANGED REGISTERS
-
-
- To have more information on function return values take a look at section 3.5, page
- 41.
-
-
- M680x0 calling conventions
- Standard entry code for procedures and functions is as follows on the 680x0 archi-
- tecture:
-
- 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 3.5, page
- 41.
-
-
- 3.4 Signalling changed registers
-
- When the compiler uses variables, it sometimes stores them, or the result of some
- calculations, in the processor registers. If you insert assembler code in your program
- that modifies the processor registers, then this may interfere with the compiler's
- idea about the registers. To avoid this problem, Free Pascal allows you to tell the
- compiler which registers have changed. The compiler will then avoid using these
- registers. Telling the compiler which registers have changed, is done by specifying
- a set of register names behind an assembly block, as follows:
-
- asm...
- end ['R1',...,'Rn'];
-
- Here R1 to Rn are the names of the 32-bit registers you modify in your assembly
- code.
- As an example :
-
- asm
- movl BP,%eax
- movl 4(%eax),%eax
- movl %eax,__RESULT
- end ['EAX'];
-
- This example tells the compiler that the EAX register was modified.
-
-
- 3.5 Register Conventions
-
- The compiler has di erent register conventions, depending on the target processor
- used.
-
- 41
-
-
-
- CHAPTER 3. USING ASSEMBLY LANGUAGE
- 3.5. REGISTER CONVENTIONS
-
-
- Intel x86 version
- When optimizations are on, no register can be freely modified, without first being
- saved and then restored. Otherwise, EDI is usually used as a scratch register and
- can be freely used in assembler blocks.
-
-
- Motorola 680x0 version
- Registers which can be freely modified without saving are registers D0, D1, D6, A0,
- A1, and floating point registers FP2 to FP7. All other registers are to be considered
- reserved and should be saved and then restored when used in assembler blocks.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 42
-
-
-
- Chapter 4
-
- Linking issues
-
- When you only use Pascal code, and Pascal units, then you will not see much of
- the part that the linker plays in creating your executable. The linker is only called
- when you compile a program. When compiling units, the linker isn't invoked.
- However, there are times that you want to link to C libraries, or to external object
- files that are generated using a C compiler (or even another pascal compiler). The
- Free Pascal compiler can generate calls to a C function, and can generate functions
- that can be called from C (exported functions). More on these calling conventions
- can be found in section 3.3, page 39.
- In general, there are 2 things you must do to use a function that resides in an
- external library or object file:
-
- 1. You must make a pascal declaration of the function or procedure you want to
- use.
-
- 2. You must tell the compiler where the function resides, i.e. in what object file
- or what library, so the compiler can link the necessary code in.
-
- The same holds for variables. To access a variable that resides in an external object
- file, you must declare it, and tell the compiler where to find it. The following
- sections attempt to explain how to do this.
-
-
- 4.1 Using external functions or procedures
-
- The first step in using external code blocks is declaring the function you want to
- use. Free Pascal supports Delphi syntax, i.e. you must use the external directive.
- The external directive replaces, in e ect, the code block of the function. As such,
- It cannot be used in an interface section of a unit, but must always reside in the
- implementation section.
- There exist four variants of the external directive :
-
- 1. A simple external declaration:
-
- Procedure ProcName (Args : TPRocArgs); external;
-
- The external directive tells the compiler that the function resides in an
- external block of code. You can use this together with the {$L } or {$LinkLib
-
- 43
-
-
-
- CHAPTER 4. LINKING
- 4.1. ISSUES
- USING EXTERNAL FUNCTIONS OR PROCEDURES
-
-
- } directives to link to a function or procedure in a library or external object
- file. Object files are looked for in the object search path (set by -Fo) and
- libraries are searched for in the linker path (set by -Fl).
-
- 2. You can give the external directive a library name as an argument:
-
- Procedure ProcName (Args : TPRocArgs); external 'Name';
-
- This tells the compiler that the procedure resides in a library with name
- 'Name'. This method is equivalent to the following:
-
- Procedure ProcName (Args : TPRocArgs);external;
- {$LinkLib 'Name'}
-
- 3. The external can also be used with two arguments:
-
- Procedure ProcName (Args : TPRocArgs); external 'Name'
- name 'OtherProcName';
-
- This has the same meaning as the previous declaration, only the compiler will
- use the name 'OtherProcName' when linking to the library. This can be used
- to give di erent names to procedures and functions in an external library.
- This method is equivalent to the following code:
-
- Procedure OtherProcName (Args : TProcArgs); external;
- {$LinkLib 'Name'}
-
- Procedure ProcName (Args : TPRocArgs);
-
- begin
- OtherProcName (Args);
- end;
-
- 4. Lastly, onder Windows and os/2, there is a fourth possibility to specify an
- external function: In .DLL files, functions also have a unique number (their
- index). It is possible to refer to these fuctions using their index:
-
- Procedure ProcName (Args : TPRocArgs); external 'Name' Index SomeIndex;
-
- This tells the compiler that the procedure ProcName resides in a dynamic link
- library, with index SomeIndex.
- Remark : Note that this is ONLY available under Windows and os/2.
-
- In earlier versions of the Free Pascal compiler, the following construct was also
- possible :
-
- Procedure ProcName (Args : TPRocArgs); [ C ];
-
- This method is equivalent to the following statement:
-
- Procedure ProcName (Args : TPRocArgs); cdecl; external;
-
- However, the [ C ] directive is no longer supported as of version 0.99.5 of Free
- Pascal, therefore you should use the external directive, with the cdecl directive,
- if needed.
-
- 44
-
-
-
- CHAPTER 4. LINKING ISSUES 4.2. USING EXTERNAL VARIABLES
-
-
- 4.2 Using external variables
-
- Some libaries or code blocks have variables which they export. You can access
- these variables much in the same way as external functions. To access an external
- variable, you declare it as follows:
-
- VarMyVar : MyType; external name 'varname';
- The e ect of this declaration is twofold:
-
- 1. No space is allocated for this variable.
- 2. The name of the variable used in the assembler code is varname. This is a
- case sensitive name, so you must be careful.
-
- The variable will be accessible with it's declared name, i.e. MyVar in this case.
- A second possibility is the declaration:
-
- Varvarname : MyType; cvar; external;
- The e ect of this declaration is twofold as in the previous case:
-
- 1. The external modifier ensures that no space is allocated for this variable.
- 2. The cvar modifier tells the compiler that the name of the variable used in
- the assembler code is exactly as specified in the declaration. This is a case
- sensitive name, so you must be careful.
-
- In this case, you access the variable with it's C name, but case insensitive. The first
- possibility allows you to change the name of the external variable for internal use.
- In order to be able to compile such statements, the compiler switch -Sv must be
- used.
- As an example, let's look at the following C file (in extvar.c):
-
- /*
- Declare a variable, allocate storage
- */
- int extvar = 12;
-
- And the following program (in extdemo.pp):
-
- Program ExtDemo;
-
- {$L extvar.o}
-
- Var { Case sensitive declaration !! }
- extvar : longint; cvar;external;
- I : longint; external name 'extvar';
- begin
- { Extvar can be used case insensitive !! }
- Writeln ('Variable ''extvar'' has value : ',ExtVar);
- Writeln ('Variable ''I'' has value : ',i);
- end.
-
- 45
-
-
-
- CHAPTER 4. LINKING ISSUES 4.3. LINKING TO AN OBJECT FILE
-
-
- Compiling the C file, and the pascal program:
-
- gcc -c -o extvar.o extvar.c
- ppc386 -Sv extdemo
-
- Will produce a program extdemo which will print
-
- Variable 'extvar' has value : 12
- Variable 'I' has value : 12
-
- on your screen.
-
-
- 4.3 Linking to an object file
-
- Having declared the external function or variable that resides in an object file,
- you can use it as if it was defined in your own program or unit. To produce an
- executable, you must still link the object file in. This can be done with the {$L
- file.o} directive.
- This will cause the linker to link in the object file file.o. On linux systems, this
- filename is case sensitive. Under dos, case isn't important. Note that file.o must
- be in the current directory if you don't specify a path. The linker will not search
- for file.o if it isn't found.
- You cannot specify libraries in this way, it is for object files only.
- Here we present an example. Consider that you have some assembly routine that
- calculates the nth Fibonacci number :
-
- .text .align 4
- .globl Fibonacci
- .type Fibonacci,@function
- Fibonacci:
- pushl %ebp
- movl %esp,%ebp
- movl 8(%ebp),%edx
- xorl %ecx,%ecx
- xorl %eax,%eax
- movl $1,%ebx
- incl %edx
- loop: decl %edx
- je endloop
- movl %ecx,%eax
- addl %ebx,%eax
- movl %ebx,%ecx
- movl %eax,%ebx
- jmp loop
- endloop:movl %ebp,%esp
- popl %ebp
- ret
-
- Then you can call this function with the following Pascal Program:
-
- 46
-
-
-
- CHAPTER 4. LINKING ISSUES 4.4. LINKING TO A LIBRARY
-
-
- Program FibonacciDemo;
-
- var i : longint;
-
- Function Fibonacci (L : longint):longint;cdecl;external;
-
- {$L fib.o}
-
- begin
- For I:=1 to 40 do
- writeln ('Fib(',i,') : ',Fibonacci (i));
- end.
-
- With just two commands, this can be made into a program :
-
- as -o fib.o fib.s
- ppc386 fibo.pp
-
- This example supposes that you have your assembler routine in fib.s, and your
- Pascal program in fibo.pp.
-
-
- 4.4 Linking to a library
-
- To link your program to a library, the procedure depends on how you declared the
- external procedure.
- In case you used the follwing syntax to declare your procedure:
-
- Procedure ProcName (Args : TPRocArgs); external 'Name';
-
- You don't need to take additional steps to link your file in, the compiler will do all
- that is needed for you. On Windows NT it will link to Name.dll, on linux your
- program will be linked to library libname, which can be a static or dynamic library.
- In case you used
-
- Procedure ProcName (Args : TPRocArgs); external;
-
- You still need to explicity link to the library. This can be done in 2 ways:
-
- 1. You can tell the compiler in the source file what library to link to using the
- {$LinkLib 'Name'} directive:
-
- {$LinkLib 'gpm'}
-
- This will link to the gpm library. On linux systems, you needn't specify the
- extension or 'lib' prefix of the library. The compiler takes care of that. On
- dos or Windows systems, you need to specify the full name.
- 2. You can also tell the compiler on the command-line to link in a library: The
- -k option can be used for that. For example
-
- ppc386 -k'-lgpm' myprog.pp
-
- Is equivalent to the above method, and tells the linker to link to the gpm
- library.
-
- 47
-
-
-
- CHAPTER 4. LINKING ISSUES 4.5. MAKING LIBRARIES
-
-
- As an example; consider the following program :
-
- program printlength;
-
- {$linklib c} { Case sensitive }
-
- { Declaration for the standard C function strlen }
- Function strlen (P : pchar) : longint; cdecl;external;
-
- begin
- Writeln (strlen('Programming is easy !'));
- end.
-
- This program can be compiled with :
-
- ppc386 prlen.pp
-
- Supposing, of course, that the program source resides in prlen.pp.
- You cannot use procedures or functions that have a variable number of arguments
- in C. Pascal doesn't support this feature of C.
-
- 4.5 Making libraries
-
- Free Pascal supports making shared or static libraries in a straightforward and easy
- manner. If you want to make libraries for other Free Pascal programmers, you just
- need to provide a command line switch. If you want C programmers to be able to
- use your code as well, you will need to adapt your code a little. This process is
- described first.
-
-
- Exporting functions
- When exporting functions from a library, there are 2 things you must take in ac-
- count:
-
- 1. Calling conventions.
- 2. Naming scheme.
-
- The calling conventions are controlled by the modifiers cdecl, popstack, pascal,
- stdcall. See section 3.3, page 39 for more information on the di erent kinds of
- calling scheme.
- The naming conventions can be controlled by 3 modifiers:
-
- cdecl: A function that has a cdecl modifier, will be used with C calling conven-
- tions, that is, the caller clears the stack. Also the mangled name will be the
- name exactly as in the declaration. cdecl is part of the function declaration,
- and hence must be present both in the interface and implementation section
- of a unit.
- export: A function that has an export modifier, uses also the exact declaration
- name as its mangled name. Under Windows NT and os/2, this modifier
- signals a function that is exported from a DLL. The calling conventions used
- by a export procedure depend on the OS. This keyword can be used only in
- the implementation section.
-
- 48
-
-
-
- CHAPTER 4. LINKING ISSUES 4.5. MAKING LIBRARIES
-
-
- Alias: The alias modifier can be used to give a supplementary assembler name
- to your function. This doesn't modify the calling conventions of the function.
-
- If you want to make your procedures and functions available to C programmers, you
- can do this very easily. All you need to do is declare the functions and procedures
- that you want to make available as export, as follows:
-
- Procedure ExportedProcedure; export;
-
- Remark : You can only declare a function as exported in the Implementation
- section of a unit. This function may not appear in the interface part of a unit. This
- is logical, since a Pascal routine cannot call an exported function, anyway.
- However, the generated object file will not contain the name of the function as you
- declared it. The Free Pascal compiler "mangles" the name you give your function.
- It makes the name all-uppercase, and adds the types of all parameters to it. There
- are cases when you want to provide a mangled name without changing the calling
- convention. In such cases, you can use the Alias modifier.
- 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).
- Remark: If you use in your unit functions that are in other units, or system
- functions, then the C program will need to link in the object files from the units
- too.
-
-
- Exporting variables
- Similarly as when you export functions, you can export variables. When exportig
- variables, one should only consider the names of the variables. To declare a variable
- that should be used by a C program, one declares it with the cvar modifier:
-
- Var MyVar : MyTpe; cvar;
-
- This will tell the compiler that the assembler name of the variable (the one which
- is used by C programs) should be exactly as specified in the declaration, i.e., case
- sensitive.
- It is not allowed to declare multiple variables as cvar in one statement, i.e. the
- following code will produce an error:
-
- var Z1,Z2 : longint;cvar;
-
-
- Compiling libraries
- Once you have your (adapted) code, with exported and other functions, you can
- compile your unit, and tell the compiler to make it into a library. The compiler will
- simply compile your unit, and perform the necessary steps to transform it into a
- static or shared (dynamical) library.
- You can do this as follows, for a dynamical library:
-
- 49
-
-
-
- CHAPTER 4. LINKING ISSUES 4.5. MAKING LIBRARIES
-
-
- ppc386 -CD myunit
-
- On linux this will leave you with a file libmyunit.so. On Windows and os/2, this
- will leave you with myunit.dll.
- If you want a static library, you can do
-
- ppc386 -CS myunit
-
- This will leave you with libmyunit.a and a file myunit.ppu. The myunit.ppu is the
- unit file needed by the Free Pascal compiler.
- The resulting files are then libraries. To make static libraries, you need the ranlib or
- ar program on your system. It is standard on any linux system, and is provided
- with the GCC compiler under dos. For the dos distribution, a copy of ar is included
- in the file gnuutils.zip.
- BEWARE: This command doesn't include anything but the current unit in the
- library. Other units are left out, so if you use code from other units, you must
- deploy them together with your library.
-
-
- Moving units into a library
- You can put multiple units into a library with the ppumove command, as follows:
-
- ppumove -e ppl -o name unit1 unit2 unit3
-
- This will move 3 units in 1 library (called libname.so on linux, name.dll on Windows)
- and it will create 3 files unit1.ppl, unit2.ppl and unit3.ppl, which are unit files, but
- which tell the compiler to look in library name when linking your executable.
- The ppumove program has options to create statical or dynamical libraries. It is
- provided with the compiler.
-
-
- Unit searching strategy
- When you compile a program or unit, the compiler will by default always look for
- .ppl files. If it doesn't find one, it will look for a .ppu file.
- To be able to di erentiate between units that have been compiled as static or
- dynamic libraries, there are 2 switches:
-
- -XD: This will define the symbol FPC LINK DYNAMIC
-
- -XS: This will define the symbol FPC LINK STATIC
-
- Definition of one symbol will automatically undefine the other.
- These two switches can be used in conjunction with the configuration file ppc386.cfg.
- The existence of one of these symbols can be used to decide which unit search path
- to set. For example:
-
- # Set unit paths
-
- #IFDEF FPC_LINK_STATIC
- -Up/usr/lib/fpc/linuxunits/staticunits
- #ENDIF
-
- 50
-
-
-
- CHAPTER 4. LINKING ISSUES 4.6. USING SMART LINKING
-
-
- #IFDEF FPC_LINK_DYNAMIC
- -Up/usr/lib/fpc/linuxunits/sharedunits
- #ENDIF
-
- With such a configuration file, the compiler will look for it's units in di erent
- directories, depending on whether -XD or -XS is used.
-
-
- 4.6 Using smart linking
-
- You can compile your units using smart linking. When you use smartlinking, the
- compiler creates a series of code blocks that are as small as possible, i.e. a code
- block will contain only the code for one procedure or function.
- When you compile a program that uses a smart-linked unit, the compiler will only
- link in the code that you actually need, and will leave out all other code. This
- will result in a smaller binary, which is loaded in memory faster, thus speeding up
- execution.
- To enable smartlinking, one can give the smartlink option on the command line :
- -Cx, or one can put the {$SMARTLINK ON} directive in the unit file:
-
- Unit Testunit
-
- {SMARTLINK ON}
- Interface
- ...
-
- Smartlinking will slow down the compilation process, especially for large units.
- When a unit foo.pp is smartlinked, the name of the codefile is changed to libfoo.a.
- Technically speaking, the compiler makes small assembler files for each procedure
- and function in the unit, as well as for all global defined variables (whether they're
- in the interface section or not). It then assembles all these small files, and uses ar
- to collect the resulting object files in one archive.
- Smartlinking and the creation of shared (or dynamic) libraries are mutually exclu-
- sive, that is, if you turn on smartlinking, then the creation of shared libraries is
- turned of. The creation of static libraries is still possible. The reason for this is
- that it has little sense in making a smarlinked dynamical library. The whole shared
- library is loaded into memory anyway by the dynamic linker (or Windows NT),
- so there would be no gain in size by making it smartlinked.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 51
-
-
-
- Chapter 5
-
- Objects
-
- In this short chapter we give some technical things about objects. For instructions
- on how to use and declare objects, see the Reference guide.
-
-
- 5.1 Constructor and Destructor calls
-
- When using objects that need virtual methods, the compiler uses two help pro-
- cedures that are in the run-time library. They are called Help Destructor and
- Help Constructor, and they are written in assembly language. 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 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 Help Destructor is inserted in every destructor declaration, just before
- the destructor's exit sequence.
-
-
- 5.2 Memory storage of objects
-
- Objects are stored in memory just as ordinary records with an extra field : a pointer
- to the Virtual Method Table (VMT). This field is stored first, and all fields in the
- object are stored in the order they are declared. This field is initialized by the call
- to the object's Constructor method.
- If the object you defined has no virtual methods, then a nil is stored in the VMT
- pointer. This ensures that the size of objects is equal, whether they have virtual
- methods or not.
- The memory allocated looks as in table (5.1).
-
-
- 5.3 The Virtual Method Table
-
- The Virtual Method Table (VMT) for each object type consists of 2 check fields
- (containing the size of the data), a pointer to the object's ancestor's VMT (Nil
-
- 52
-
-
-
- CHAPTER 5. OBJECTS 5.3. THE VIRTUAL METHOD TABLE
-
-
-
- Table 5.1: Object memory layout
-
- O set What
- +0 Pointer to VMT.
- +4 Data. All fields in the order the've been declared.
- ...
-
-
- Table 5.2: Virtual Method Table memory layout
-
- O set What
- +0 Size of object type data
- +4 Minus the size of object type data. Enables determining of valid VMT pointers.
- +8 Pointer to ancestor VMT, Nil if no ancestor available.
- +12 Pointers to the virtual methods.
- ...
-
-
- if there is no ancestor), and then the pointers to all virtual methods. The VMT
- layout is illustrated in table (5.2).
- The VMT is constructed by the compiler. Every instance of an object receives a
- pointer to its VMT.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 53
-
-
-
- Chapter 6
-
- Generated code
-
- The Free Pascal compiler relies on the assembler to make object files. It generates
- just the assembly language file. In the following two sections, we discuss what is
- generated when you compile a unit or a program.
-
-
- 6.1 Units
-
- When you compile a unit, the Free Pascal compiler generates 2 files :
-
- 1. A unit description file (with extension .ppu, or .ppw on Windows NT ).
-
- 2. An assembly language file (with extension .s).
-
- The assembly language file contains the actual source code for the statements in
- your unit, and the necessary memory allocations for any variables you use in your
- unit. This file is converted by the assembler to an object file (with extension .o)
- which can then be linked to other units and your program, to form an executable.
- By default (compiler version 0.9.4 and up), the assembly file is removed after it
- has been compiled. Only in the case of the -s command-line option, the assembly
- file must be left on disk, so the assembler can be called later. You can disable the
- erasing of the assembler file with the -a switch.
- The unit file contains all the information the compiler needs to use the unit:
-
- 1. Other used units, both in interface and implementation.
-
- 2. Types and variables from the interface section of the unit.
-
- 3. Function declarations from the interface section of the unit.
-
- 4. Some debugging information, when compiled with debugging.
-
- 5. A date and time stamp.
-
- Macros, symbols and compiler directives are not saved to the unit description file.
- Aliases for functions are also not written to this file, which is logical, since they
- cannot appear in the interface section of a unit.
- The detailed contents and structure of this file are described in the first appendix.
- You can examine a unit description file using the dumpppu program, which shows
- the contents of the file.
-
- 54
-
-
-
- CHAPTER 6. GENERATED CODE 6.2. PROGRAMS
-
-
- If you want to distribute a unit without source code, you must provide both the
- unit description file and the object file.
- You can also provide a C header file to go with the object file. In that case, your
- unit can be used by someone who wishes to write his programs in C. However, you
- must make this header file yourself since the Free Pascal compiler doesn't make one
- for you.
-
-
- 6.2 Programs
-
- When you compile a program, the compiler produces again 2 files :
-
- 1. An assembly language file containing the statements of your program, and
- memory allocations for all used variables.
-
- 2. A linker response file. This file contains a list of object files the linker must
- link together.
-
- The link response file is, by default, removed from the disk. Only when you specify
- the -s command-line option or when linking fails, then the file is left on the disk.
- It is named link.res.
- The assembly language file is converted to an object file by the assembler, and then
- linked together with the rest of the units and a program header, to form your final
- program.
- The program header file is a small assembly program which provides the entry point
- for the program. This is where the execution of your program starts, so it depends
- on the operating system, because operating systems pass parameters to executables
- in wildly di erent ways.
- It's name is prt0.o, and the source file resides in prt0.s or some variant of this name.
- It usually resided where the system unit source for your system resides. It's main
- function is to save the environment and command-line arguments and set up the
- stack. Then it calls the main program.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 55
-
-
-
- Chapter 7
-
- Intel MMX support
-
- 7.1 What is it about ?
-
- Free Pascal supports the new MMX (Multi-Media extensions) instructions of Intel
- processors. The idea of MMX is to process multiple data with one instruction,
- for example the processor can add simultaneously 4 words. To implement this
- e ciently, the Pascal language needs to be extended. So Free Pascal allows to
- add for example two array[0..3] of word, if MMX support is switched on. The
- operation is done by the MMX unit and allows people without assembler knowledge
- to take advantage of the MMX extensions.
- Here is an example:
-
- usesMMX; { include some predefined data types }
- const
- { tmmxword = array[0..3] of word;, declared by unit MMX }
- w1 : tmmxword = (111,123,432,4356);
- w2 : tmmxword = (4213,63456,756,4);
-
- varw3 : tmmxword;
- l : longint;
-
- begin
- if is_mmx_cpu then { is_mmx_cpu is exported from unit mmx }
- begin
- {$mmx+} { turn mmx on }
- w3:=w1+w2;
- {$mmx-}
- end
- else
- begin
- for i:=0 to 3 do
- w3[i]:=w1[i]+w2[i];
- end;
- end.
-
-
- 56
-
-
-
- CHAPTER 7. INTEL MMX SUPPORT 7.2. SATURATION SUPPORT
-
-
- 7.2 Saturation support
-
- One important point of MMX is the support of saturated operations. If a operation
- would cause an overflow, the value stays at the highest or lowest possible value for
- the data type: If you use byte values you get normally 250+12=6. This is very
- annoying when doing color manipulations or changing audio samples, when you
- have to do a word add and check if the value is greater than 255. The solution
- is saturation: 250+12 gives 255. Saturated operations are supported by the MMX
- unit. If you want to use them, you have simple turn the switch saturation on:
- $saturation+
- Here is an example:
-
- Program SaturationDemo;
- { example for saturation, scales data (for example audio)
- with 1.5 with rounding to negative infinity
- }
-
- varaudio1 : tmmxword;
- const
- helpdata1 : tmmxword = ($c000,$c000,$c000,$c000);
- helpdata2 : tmmxword = ($8000,$8000,$8000,$8000);
-
- begin
- { audio1 contains four 16 bit audio samples }
- {$mmx+}
- { convert it to $8000 is defined as zero, multiply data with 0.75 }
- audio1:=tmmxfixed16(audio1+helpdata2)*tmmxfixed(helpdata1);
- {$saturation+}
- { avoid overflows (all values>$7fff becomes $ffff) }
- audio1:=(audio1+helpdata2)-helpdata2;
- {$saturation-}
- { now mupltily with 2 and change to integer }
- audio1:=(audio1 shl 1)-helpdata2;
- {$mmx-}
- end.
-
-
- 7.3 Restrictions of MMX support
-
- In the beginning of 1997 the MMX instructions were introduced in the Pentium
- processors, so multitasking systems wouldn't save the newly introduced MMX reg-
- isters. To work around that problem, Intel mapped the MMX registers to the FPU
- register.
- The consequence is that you can't mix MMX and floating point operations. After
- using MMX operations and before using floating point operations, you have to call
- the routine EMMS of the MMX unit. This routine restores the FPU registers.
- Careful: The compiler doesn't warn if you mix floating point and MMX operations,
- so be careful.
- The MMX instructions are optimized for multi media (what else?). So it isn't
-
- 57
-
-
-
- CHAPTER 7. INTEL MMX SUPPORT7.4. SUPPORTED MMX OPERATIONS
-
-
- possible to perform each operation, some opertions give a type mismatch, see section
- 7.4 for the supported MMX operations
- An important restriction is that MMX operations aren't range or overflow checked,
- even when you turn range and overflow checking on. This is due to the nature of
- MMX operations.
- The MMX unit must always be used when doing MMX operations because the exit
- code of this unit clears the MMX unit. If it wouldn't do that, other program will
- crash. A consequence of this is that you can't use MMX operations in the exit code
- of your units or programs, since they would interfere with the exit code of the MMX
- unit. The compiler can't check this, so you are responsible for this !
-
-
- 7.4 Supported MMX operations
-
- Still to be written...
-
-
- 7.5 Optimizing MMX support
-
- Here are some helpful hints to get optimal performance:
-
- * The EMMS call takes a lot of time, so try to seperate floating point and MMX
- operations.
-
- * Use MMX only in low level routines because the compiler saves all used MMX
- registers when calling a subroutine.
-
- * The NOT-operator isn't supported natively by MMX, so the compiler has to
- generate a workaround and this operation is ine cient.
-
- * Simple assignements of floating point numbers don't access floating point reg-
- isters, so you need no call to the EMMS procedure. Only when doing arithmetic,
- you need to call the EMMS procedure.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 58
-
-
-
- Chapter 8
-
- Memory issues
-
- 8.1 The 32-bit model.
-
- The Free Pascal compiler issues 32-bit code. This has several consequences:
-
- * You need a 386 processor to run the generated code. The compiler functions
- on a 286 when you compile it using Turbo Pascal, but the generated programs
- cannot be assembled or executed.
- * You don't need to bother with segment selectors. Memory can be addressed
- using a single 32-bit pointer. The amount of memory is limited only by the
- available amount of (virtual) memory on your machine.
- * The structures you define are unlimited in size. Arrays can be as long as you
- want. You can request memory blocks from any size.
-
- The fact that 32-bit code is used, means that some of the older Turbo Pascal
- constructs and functions are obsolete. The following is a list of functions which
- shouldn't be used anymore:
-
- Seg() : Returned the segment of a memory address. Since segments have no more
- meaning, zero is returned in the Free Pascal run-time library implementation
- of Seg.
- Ofs() : Returned the o set of a memory address. Since segments have no more
- meaning, the complete address is returned in the Free Pascal implementation
- of this function. This has as a consequence that the return type is Longint
- instead of Word.
- Cseg(), Dseg() : Returned, respectively, the code and data segments of your
- program. This returns zero in the Free Pascal implementation of the system
- unit, since both code and data are in the same memory space.
- Ptr: Accepted a segment and o set from an address, and would return a pointer
- to this address. This has been changed in the run-time library. Standard it
- returns now simply the o set. If you want to retain the old functionality, you
- can recompile the run-time library with the DoMapping symbol defined. This
- will restore the Turbo Pascal behaviour.
- memw and mem These arrays gave access to the dos memory. Free Pascal sup-
- ports them on the go32v2 platform, they are mapped into dos memory space.
- You need the GO32 unit for this. On other platforms, they are not supported
-
- 59
-
-
-
- CHAPTER 8. MEMORY ISSUES 8.2. THE STACK
-
-
-
- Table 8.1: Stack frame when calling a procedure
-
- O set What is stored Optional ?
- +x parameters Yes
- +12 function result Yes
- +8 self Yes
- +4 Frame pointer of parent procedure Yes
- +0 Return address No
-
-
- You shouldn't use these functions, since they are very non-portable, they're specific
- to dos and the ix86 processor. The Free Pascal compiler is designed to be portable
- to other platforms, so you should keep your code as portable as possible, and not
- system specific. That is, unless you're writing some driver units, of course.
-
-
- 8.2 The stack
-
- The stack is used to pass parameters to procedures or functions, to store local
- variables, and, in some cases, to return function results.
- 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 (8.1).
-
-
- Intel x86 version
- The stack is cleared with the ret I386 instruction, meaning that the size of all
- pushed parameters is limited to 64K.
-
- DOS
-
- Under the DOS targets, the default stack is set to 256Kb. This value cannot be
- modified for the GO32V1 target. But this can be modified with the GO32V2 target
- using a special DJGPP utility stubedit. It is to note that the stack size may be
- changed with some compiler switches, this stack size, if greater then the default
- stack size will be used instead, otherwise the default stack size is used.
-
-
- 60
-
-
-
- CHAPTER 8. MEMORY ISSUES 8.3. THE HEAP
-
-
- Linux
-
- Under Linux, stack size is only limited by the available memory of the system.
-
- OS/2
-
- Under OS/2, stack size is determined by one of the runtime environment variables
- set for EMX. Therefore, the stack size is user defined.
-
-
- Motorola 680x0 version
- All depending on the processor target, the stack can be cleared in two manners, if
- the target processor is a MC68020 or higher, the stack will be cleared with a simple
- rtd instruction, meaning that the size of all pushed parameters is limited to 32K.
- Otherwise on MC68000/68010 processors, the stack clearing mechanism is sligthly
- more complicated, the exit code will look like this:
-
- { move.l (sp)+,a0
- add.l paramsize,a0
- move.l a0,-(sp)
- rts
- }
-
- Amiga
-
- Under AmigaOS, stack size is determined by the user, which sets this value using
- the stack program. Typical sizes range from 4K to 40K.
-
- Atari
-
- Under Atari TOS, stack size is currently limited to 8K, and it cannot be modified.
- This may change in a future release of the compiler.
-
-
- 8.3 The heap
-
- The heap is used to store all dynamic variables, and to store class instances. The
- interface to the heap is the same as in Turbo Pascal, although the e ects are maybe
- not the same. On top of that, the Free Pascal run-time library has some extra
- possibilities, not available in Turbo Pascal. These extra possibilities are explained
- in the next subsections.
-
-
- The heap grows
- Free Pascal supports the HeapError procedural variable. If this variable is non-nil,
- then it is called in case you try to allocate memory, and the heap is full. By default,
- HeapError points to the GrowHeap function, which tries to increase the heap.
- The growheap function issues a system call to try to increase the size of the memory
- available to your program. It first tries to increase memory in a 1 Mb. chunk. If
- this fails, it tries to increase the heap by the amount you requested from the heap.
-
- 61
-
-
-
- CHAPTER 8. MEMORY ISSUES 8.3. THE HEAP
-
-
- If the call to GrowHeap has failed, then a run-time error is generated, or nil is
- returned, depending on the GrowHeap result.
- If the call to GrowHeap was successful, then the needed memory will be allocated.
-
-
- Using Blocks
- If you need to allocate a lot of small blocks for a small period, then you may
- want to recompile the run-time library with the USEBLOCKS symbol defined. If it is
- recompiled, then the heap management is done in a di erent way.
- The run-time library keeps a linked list of allocated blocks with size up to 256
- bytes1. By default, it keeps 32 of these lists2.
- When a piece of memory in a block is deallocated, the heap manager doesn't re-
- ally deallocate the occupied memory. The block is simply put in the linked list
- corresponding to its size.
- When you then again request a block of memory, the manager checks in the list if
- there is a non-allocated block which fits the size you need (rounded to 8 bytes). If
- so, the block is used to allocate the memory you requested.
- This method of allocating works faster if the heap is very fragmented, and you
- allocate a lot of small memory chunks.
- Since it is invisible to the program, this provides an easy way of improving the
- performance of the heap manager.
-
-
- Using the split heap
- Remark : The split heap is still somewhat buggy. Use at your own risk for the
- moment.
- The split heap can be used to quickly release a lot of blocks you allocated previously.
- Suppose that in a part of your program, you allocate a lot of memory chunks on
- the heap. Suppose that you know that you'll release all this memory when this
- particular part of your program is finished.
- In Turbo Pascal, you could foresee this, and mark the position of the heap (using
- the Mark function) when entering this particular part of your program, and release
- the occupied memory in one call with the Release call.
- For most purposes, this works very good. But sometimes, you may need to allo-
- cate something on the heap that you don't want deallocated when you release the
- allocated memory. That is where the split heap comes in.
- When you split the heap, the heap manager keeps 2 heaps: the base heap (the
- normal heap), and the temporary heap. After the call to split the heap, memory
- is allocated from the temporary heap. When you're finished using all this memory,
- you unsplit the heap. This clears all the memory on the split heap with one call.
- After that, memory will be allocated from the base heap again.
- So far, nothing special, nothing that can't be done with calls to mark and release.
- Suppose now that you have split the heap, and that you've come to a point where
- you need to allocate memory that is to stay allocated after you unsplit the heap
- again. At this point, mark and release are of no use. But when using the split heap,
- you can tell the heap manager to ¡temporarily¡ use the base heap again to allocate
- 1The size can be set using the max size constant in the heap.inc source file.
- 2The actual size is max size div 8.
-
-
- 62
-
-
-
- CHAPTER 8. MEMOR
- 8.4. Y ISSUES
- USING DOS MEMORY UNDER THE GO32 EXTENDER
-
-
- memory. When you've allocated the needed memory, you can tell the heap manager
- that it should start using the temporary heap again. When you're finished using
- the temporary heap, you release it, and the memory you allocated on the base heap
- will still be allocated.
- To use the split-heap, you must recompile the run-time library with the TempHeap
- symbol defined. This means that the following functions are available :
-
- procedure Split_Heap;
- procedure Switch_To_Base_Heap;
- procedure Switch_To_Temp_Heap;
- procedure Switch_Heap;
- procedure ReleaseTempHeap;
- procedure GetTempMem(var p : pointer;size : longint);
-
- Split Heap is used to split the heap. It cannot be called two times in a row, without
- a call to releasetempheap. Releasetempheap completely releases the memory used
- by the temporary heap. Switching temporarily back to the base heap can be done
- using the Switch To Base Heap call, and returning to the temporary heap is done
- using the Switch To Temp Heap call. Switching from one to the other without
- knowing on which one your are right now, can be done using the Switch Heap call,
- which will split the heap first if needed.
- A call to GetTempMem will allocate a memory block on the temporary heap, whatever
- the current heap is. The current heap after this call will be the temporary heap.
- Typically, what will appear in your code is the following sequence :
-
- Split_Heap
- ...
- { Memory allocation }
- ...
- { !! non-volatile memory needed !!}
- Switch_To_Base_Heap;
- getmem (P,size);
- Switch_To_Temp_Heap;
- ...
- {Memory allocation}
- ...
- ReleaseTempHeap;
- {All allocated memory is now freed, except for the memory pointed to by 'P' }
- ...
-
-
- 8.4 Using dos memory under the Go32 extender
-
- Because Free Pascal is a 32 bit compiler, and uses a dos extender, accessing DOS
- memory isn't trivial. What follows is an attempt to an explanation of how to access
- and use dos or real mode memory3.
- In Proteced Mode, memory is accessed through Selectors and O sets. You can think
- of Selectors as the protected mode equivalents of segments.
- In Free Pascal, a pointer is an o set into the DS selector, which points to the Data
- of your program.
- 3Thanks to an explanation of Thomas schatzl (E-mail:tom at work@geocities.com).
-
-
- 63
-
-
-
- CHAPTER 8. MEMOR
- 8.4. Y ISSUES
- USING DOS MEMORY UNDER THE GO32 EXTENDER
-
-
- To access the (real mode) dos memory, somehow you need a selector that points
- to the dos memory. The GO32 unit provides you with such a selector: The
- DosMemSelector variable, as it is conveniently called.
- You can also allocate memory in dos's memory space, using the global dos alloc
- function of the GO32 unit. This function will allocate memory in a place where dos
- sees it.
- As an example, here is a function that returns memory in real mode dos and returns
- a selector:o set pair for it.
-
- procedure dosalloc(var selector : word;
- var segment : word;
- size : longint);
-
- var result : longint;
-
- beginresult := global_dos_alloc(size);
- selector := word(result);
- segment := word(result shr 16);
- end;
-
- (You need to free this memory using the global dos free function.)
- You can access any place in memory using a selector. You can get a selector using
- the allocate ldt descriptor function, and then let this selector point to the
- physical memory you want using the set segment base address function, and set
- its length using set segment limit function. You can manipulate the memory
- pointed to by the selector using the functions of the GO32 unit. For instance with
- the seg fillchar function. After using the selector, you must free it again using
- the free ldt selector function.
- More information on all this can be found in the Unit reference, the chapter on the
- GO32 unit.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 64
-
-
-
- Chapter 9
-
- Optimizations
-
- 9.1 Non processor specific
-
- The following sections describe the general optimizations done by the compiler, they
- are not processor specific. Some of these require some compiler switch override while
- others are done automatically (those which require a switch will be noted as such).
-
-
- Constant folding
- In Free Pascal, if the operand(s) of an operator are constants, they will be evaluated
- at compile time.
- Example
-
- x:=1+2+3+6+5;
- will generate the same code as
- x:=17;
-
- Furthermore, if an array index is a constant, the o set will be evaluated at compile
- time. This means that accessing MyData[5] is as e cient as accessing a normal
- variable.
- Finally, calling Chr, Hi, Lo, Ord, Pred, or Succ functions with constant parameters
- generates no run-time library calls, instead, the values are evaluated at compile
- time.
-
-
- Constant merging
- Using the same constant string two or more times generates only one copy of the
- string constant.
-
-
- Short cut evaluation
- Evaluation of boolean expression stops as soon as the result is known, which makes
- code execute faster then if all boolean operands were evaluated.
-
-
-
-
- 65
-
-
-
- CHAPTER 9. OPTIMIZATIONS 9.1. NON PROCESSOR SPECIFIC
-
-
- Constant set inlining
- Using the in operator is always more e cient then using the equivalent <>, =, <=,
- >=, < and > operators. This is because range comparisons can be done more easily
- with in then with normal comparison operators.
-
-
- Small sets
- Sets which contain less then 33 elements can be directly encoded using a 32-bit
- value, therefore no run-time library calls to evaluate operands on these sets are
- required; they are directly encoded by the code generator.
-
-
- Range checking
- Assignments of constants to variables are range checked at compile time, which
- removes the need of the generation of runtime range checking code.
- Remark: This feature was not implemented before version 0.99.5 of Free Pascal.
-
-
- Shifts instead of multiply or divide
- When one of the operands in a multiplication is a power of two, they are encoded
- using arithmetic shift instructions, which generates more e cient code.
- Similarly, if the divisor in a div operation is a power of two, it is encoded using
- arithmetic shift instructions.
- The same is true when accessing array indexes which are powers of two, the address
- is calculated using arithmetic shifts instead of the multiply instruction.
-
-
- Automatic alignment
- By default all variables larger then a byte are guaranteed to be aligned at least on
- a word boundary.
- Furthermore all pointers allocated using the standard runtime library (New and
- GetMem among others) are guaranteed to return pointers aligned on a quadword
- boundary (64-bit alignment).
- Alignment of variables on the stack depends on the target processor.
- Remark: Quadword alignment of pointers is not guaranteed on systems which
- don't use an internal heap, such as for the Win32 target.
- Remark: Alignment is also done between fields in records, objects and classes, this
- is not the same as in Turbo Pascal and may cause problems when using disk I/O
- with these types. To get no alignment between fields use the packed directive or
- the {$PackRecords n} switch. For further information, take a look at the reference
- manual under the record heading.
-
-
- Smart linking
- This feature removes all unreferenced code in the final executable file, making the
- executable file much smaller.
- Smart linking is switched on with the -Cx command-line switch, or using the
- {$SMARTLINK ON} global directive.
-
-
- 66
-
-
-
- CHAPTER 9. OPTIMIZATIONS 9.1. NON PROCESSOR SPECIFIC
-
-
- Remark: Smart linking was implemented starting with version 0.99.6 of Free
- Pascal.
-
-
- Inline routines
- The following runtime library routines are coded directly into the final executable
- : Lo, Hi, High, Sizeof, TypeOf, Length, Pred, Succ, Inc, Dec and Assigned.
- Remark: Inline Inc and Dec were not completely implemented until version 0.99.6
- of Free Pascal.
-
-
- Case optimization
- When using the -O1 (or higher) switch, case statements will be generated using a
- jump table if appropriate, to make them execute faster.
-
-
- Stack frame omission
- Under specific conditions, the stack frame (entry and exit code for the routine, see
- section 3.3) will be omitted, and the variable will directly be accessed via the stack
- pointer.
- Conditions for omission of the stack frame :
-
- * The function has no parameters nor local variables.
-
- * Routine does not call other routines.
-
- * Routine does not contain assembler statements. However, a assembler rou-
- tine may omit it's stack frame.
-
- * Routine is not declared using the Interrupt directive.
-
- * Routine is not a constructor or destructor.
-
-
- Register variables
- When using the -Or switch, local variables or parameters which are used very often
- will be moved to registers for faster access.
- Remark: Register variable allocation is currently an experimental feature, and
- should be used with caution.
-
-
- Intel x86 specific
- Here follows a listing of the optimizing techniques used in the compiler:
-
- 1. When optimizing for a specific Processor (-Op1, -Op2, -Op3, the following
- is done:
-
- * In case statements, a check is done whether a jump table or a sequence
- of conditional jumps should be used for optimal performance.
- * Determines a number of strategies when doing peephole optimization,
- e.g.: movzbl (%ebp), %eax will be changed into xorl %eax,%eax; movb
- (%ebp),%al for Pentium and PentiumMMX.
-
- 67
-
-
-
- CHAPTER 9. OPTIMIZATIONS 9.1. NON PROCESSOR SPECIFIC
-
-
- 2. When optimizing for speed (-OG, the default) or size (-Og), a choice is made
- between using shorter instructions (for size) such as enter $4, or longer in-
- structions subl $4,%esp for speed. When smaller size is requested, things
- aren't aligned on 4-byte boundaries. When speed is requested, things are
- aligned on 4-byte boundaries as much as possible.
- 3. Fast optimizations (-O1): activate the peephole optimizer
- 4. Slower optimizations (-O2): also activate the common subexpression elimina-
- tion (formerly called the "reloading optimizer")
- 5. Uncertain optimizations (-Ou): With this switch, the common subexpression
- elimination algorithm can be forced into making uncertain optimizations.
- Although you can enable uncertain optimizations in most cases, for people
- who do not understand the following technical explanation, it might be the
- safest to leave them o .
-
- If uncertain optimizations are enabled, the CSE algortihm assumes
- that
- * If something is written to a local/global register or a proce-
- dure/function parameter, this value doesn't overwrite the value
- to which a pointer points.
- * If something is written to memory pointed to by a pointer vari-
- able, this value doesn't overwrite the value of a local/global vari-
- able or a procedure/function parameter.
- The practical upshot of this is that you cannot use the uncertain optimiza-
- tions if you both write and read local or global variables directly and through
- pointers (this includes Var parameters, as those are pointers too).
- The following example will produce bad code when you switch on uncertain
- optimizations:
-
- Var temp: Longint;
-
- Procedure Foo(Var Bar: Longint);
- Begin
- If (Bar = temp)
- Then
- Begin
- Inc(Bar);
- If (Bar <> temp) then Writeln('bug!')
- End
- End;
-
- Begin
- Foo(Temp);
- End.
-
- The reason it produces bad code is because you access the global variable Temp
- both through its name Temp and through a pointer, in this case using the Bar
- variable parameter, which is nothing but a pointer to Temp in the above code.
- On the other hand, you can use the uncertain optimizations if you access
- global/local variables or parameters through pointers, and only access them
- through this pointer1.
- 1 You can use multiple pointers to point to the same variable as well, that doesn't matter.
-
-
- 68
-
-
-
- CHAPTER 9. OPTIMIZATIONS 9.2. OPTIMIZATION SWITCHES
-
-
- For example:
-
- Type TMyRec = Record
- a, b: Longint;
- End;
- PMyRec = ^TMyRec;
-
-
- TMyRecArray = Array [1..100000] of TMyRec;
- PMyRecArray = ^TMyRecArray;
-
- Var MyRecArrayPtr: PMyRecArray;
- MyRecPtr: PMyRec;
- Counter: Longint;
-
- Begin
- New(MyRecArrayPtr);
- For Counter := 1 to 100000 Do
- Begin
- MyRecPtr := @MyRecArrayPtr^[Counter];
- MyRecPtr^.a := Counter;
- MyRecPtr^.b := Counter div 2;
- End;
- End.
-
- Will produce correct code, because the global variable MyRecArrayPtr is not
- accessed directly, but only through a pointer (MyRecPtr in this case).
- In conclusion, one could say that you can use uncertain optimizations only
- when you know what you're doing.
-
-
- Motorola 680x0 specific
- Using the -O2 switch does several optimizations in the code produced, the most
- notable being:
-
- * Sign extension from byte to long will use EXTB
- * Returning of functions will use RTD
- * Range checking will generate no run-time calls
- * Multiplication will use the long MULS instruction, no runtime library call will
- be generated
- * Division will use the long DIVS instruction, no runtime library call will be
- generated
-
-
- 9.2 Optimization switches
-
- This is where the various optimizing switches and their actions are described,
- grouped per switch.
-
- -On: with n = 1..3: these switches activate the optimizer. A higher level auto-
- matically includes all lower levels.
-
- 69
-
-
-
- CHAPTER 9. OPTIMIZATIONS 9.3. TIPS TO GET FASTER CODE
-
-
- * Level 1 (-O1) activates the peephole optimizer (common instruction se-
- quences are replaced by faster equivalents).
- * Level 2 (-O2) enables the assembler data flow analyzer, which allows
- the common subexpression elimination procedure to remove unnecessary
- reloads of registers with values they already contain.
- * Level 3 (-O3) enables uncertain optimizations. For more info, see -Ou.
-
- -OG: This causes the code generator (and optimizer, IF activated), to favor faster,
- but code-wise larger, instruction sequences (such as "subl $4,%esp") instead
- of slower, smaller instructions ("enter $4"). This is the default setting.
-
- -Og: This one is exactly the reverse of -OG, and as such these switches are mu-
- tually exclusive: enabling one will disable the other.
-
- -Or: This setting (once it's fixed) causes the code generator to check which vari-
- ables are used most, so it can keep those in a register.
-
- -Opn: with n = 1..3: Setting the target processor does NOT activate the opti-
- mizer. It merely influences the code generator and, if activated, the optimizer:
-
- * During the code generation process, this setting is used to decide whether
- a jump table or a sequence of successive jumps provides the best perfor-
- mance in a case statement.
- * The peephole optimizer takes a number of decisions based on this setting,
- for example it translates certain complex instructions, such as
- movzbl (mem), %eax|
- to a combination of simpler instructions
- xorl %eax, %eax
- movb (mem), %al
- for the Pentium.
-
- -Ou: This enables uncertain optimizations. You cannot use these always, however.
- The previous section explains when they can be used, and when they cannot
- be used.
-
-
- 9.3 Tips to get faster code
-
- Here, some general tips for getting better code are presented. They mainly concern
- coding style.
-
- * Find a better algorithm. No matter how much you and the compiler tweak the
- code, a quicksort will (almost) always outperform a bubble sort, for example.
-
- * Use variables of the native size of the processor you're writing for. For the
- 80x86 and compatibles, this is 32 bit, so you're best of using longint and
- cardinal variables.
-
- * Turn on the optimizer.
-
- * Write your if/then/else statements so that the code in the "then"-part gets
- executed most of the time (improves the rate of successful jump prediction).
-
-
-
- 70
-
-
-
- CHAPTER 9. OPTIMIZATIONS 9.4. FLOATING POINT
-
-
- * If you are allocating and disposing a lot of small memory blocks, check out
- the heapblocks variable (heapblocks are on by default from release 0.99.8 and
- later)
-
- * Profile your code (see the -pg switch) to find out where the bottlenecks are.
- If you want, you can rewrite those parts in assembler. You can take the code
- generated by the compiler as a starting point. When given the -a command-
- line switch, the compiler will not erase the assembler file at the end of the
- assembly process, so you can study the assembler file.
- Note: Code blocks which contain an assembler block, are not processed at all
- by the optimizer at this time. Update: as of version 0.99.11, the Pascal code
- surrounding the assembler blocks is optimized.
-
-
- 9.4 Floating point
-
- This is where can be found processor specific information on floating point code
- generated by the compiler.
-
-
- Intel x86 specific
- All normal floating point types map to their real type, including comp and extended.
-
-
- Motorola 680x0 specific
- Early generations of the Motorola 680x0 processors did not have integrated floating
- point units, so to circumvent this fact, all floating point operations are emulated
- (with the $E+ switch, which is the default) using the IEEE Single floating point
- type. In other words when emulation is on, Real, Single, Double and Extended all
- map to the single floating point type.
- When the $E switch is turned o , normal 68882/68881/68040 floating point opcodes
- are emitted. The Real type still maps to Single but the other types map to their
- true floating point types. Only basic FPU opcodes are used, which means that it
- can work on 68040 processors correctly.
- Remark: Double and Extended types in true floating point mode have not been
- extensively tested as of version 0.99.5.
- Remark: The comp data type is currently not supported.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 71
-
-
-
- Appendix A
-
- Anatomy of a unit file
-
- A.1 Basics
-
- The best and most updated documentation about the ppu files can be found in
- ppu.pas and ppudump.pp which can be found in rtl/utils/.
- To read or write the ppufile, you can use the ppu unit ppu.pas which has an object
- called tppufile which holds all routines that deal with ppufile handling. While
- describing the layout of a ppufile, the methods which can be used for it are presented
- as well.
- A unit file consists of basically five or six parts:
-
- 1. A unit header.
-
- 2. A file interface part.
-
- 3. A definition part. Contains all type and procedure definitions.
-
- 4. A symbol part. Contains all symbol names and references to their definitions.
-
- 5. A browser part. Contains all references from this unit to other units and
- inside this unit. Only available when the uf has browser flag is set in the
- unit flags
-
- 6. A file implementation part (currently unused).
-
-
- A.2 reading ppufiles
-
- We will first create an object ppufile which will be used below. We are opening unit
- test.ppu as an example.
-
- varppufile : pppufile;
- begin
- { Initialize object }
- ppufile:=new(pppufile,init('test.ppu');
- { open the unit and read the header, returns false when it fails }
- if not ppufile.open then
- error('error opening unit test.ppu');
-
- 72
-
-
-
- APPENDIX A. ANATOMY OF A UNIT FILE A.3. THE HEADER
-
-
-
- { here we can read the unit }
-
- { close unit }
- ppufile.close;
- { release object }
- dispose(ppufile,done);
- end;
-
- Note: When a function fails (for example not enough bytes left in an entry) it sets
- the ppufile.error variable.
-
-
- A.3 The Header
-
- The header consists of a record containing 24 bytes:
-
- tppuheader=packed record
- id : array[1..3] of char; { = 'PPU' }
- ver : array[1..3] of char;
- compiler : word;
- cpu : word;
- target : word;
- flags : longint;
- size : longint; { size of the ppufile without header }
- checksum : longint; { checksum for this ppufile }
- end;
-
- The header is already read by the ppufile.open command. You can access all
- fields using ppufile.header which holds the current header record.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 73
-
-
-
- APPENDIX A. ANATOMY OF A UNIT FILE A.4. THE SECTIONS
-
-
- field description
- id this is allways 'PPU', can be checked with
- function ppufile.CheckPPUId:boolean;
- ver ppu version, currently '015', can be checked with
- function ppufile.GetPPUVersion:longint; (returns 15)
- compiler compiler version used to create the unit. Doesn't contain the
- patchlevel. Currently 0.99 where 0 is the high byte and 99 the
- low byte
- cpu cpu for which this unit is created. 0 = i386 1 = m68k
- target target for which this unit is created, this depends also on the cpu!
- For i386: 0 Go32v1
- 1 Go32V2
- 2 Linux-i386
- 3 OS/2
- 4 Win32
- For m68k: 0 Amiga
- 1 Mac68k
- 2 Atari
- 3 Linux-m68k
- flag the unit flags, contains a combination of the uf constants which
- are definied in ppu.pas
- size size of this unit without this header
- checksum checksum of the interface parts of this unit, which determine if a
- unit is changed or not, so other units can see if they need to be
- recompiled
-
- A.4 The sections
-
- After this header follow the sections. All sections work the same! A section consists
- of entries and ends also with an entry, but containing the specific ibend constant
- (see ppu.pas for a list of constants).
- Each entry starts with an entryheader.
-
- tppuentry=packed record
- id : byte;
- nr : byte;
- size : longint;
- end;
-
- field Description
- id this is 1 or 2 and can be checked to see whether the entry is
- correctly found. 1 means its a main entry, which says that it is
- part of the basic layout as explained before. 2 means that it it a
- sub entry of a record or object.
- nr contains the ib constant number which determines what kind of
- entry it is.
- size size of this entry without the header, can be used to skip entries
- very easily.
- To read an entry you can simply call ppufile.readentry:byte, it returns the
- tppuentry.nr field, which holds the type of the entry. A common way how this
- works is (example is for the symbols):
-
- repeat
-
- 74
-
-
-
- APPENDIX A. ANATOMY OF A UNIT FILE A.5. CREATING PPUFILES
-
-
- b:=ppufile.readentry;
- case b of
- ib<etc> : begin
- end;
- ibendsyms : break;
- end;
- until false;
-
- Then you can parse each entry type yourself. ppufile.readentry will take care
- of skipping unread bytes in the entry and reads the next entry correctly! A special
- function is skipuntilentry(untilb:byte):boolean; which will read the ppufile
- until it finds entry untilb in the main entries.
- Parsing an entry can be done with ppufile.getxxx functions. The available func-
- tions are:
-
- procedure ppufile.getdata(var b;len:longint);
- function getbyte:byte;
- function getword:word;
- function getlongint:longint;
- function getreal:ppureal;
- function getstring:string;
-
- To check if you're at the end of an entry you can use the following function:
-
- function EndOfEntry:boolean;
-
- notes:
-
- 1. ppureal is the best real that exists for the cpu where the unit is created for.
- Currently it is extended for i386 and single for m68k.
- 2. the ibobjectdef and ibrecorddef have stored a definition and symbol sec-
- tion for themselves. So you'll need a recursive call. See ppudump.pp for a
- correct implementation.
-
- A complete list of entries and what their fields contain can be found in ppudump.pp.
-
-
- A.5 Creating ppufiles
-
- Creating a new ppufile works almost the same as writing. First you need to init the
- object and call create:
-
- ppufile:=new(pppufile,'output.ppu');
- ppufile.create;
-
- After that you can simply write all needed entries. You'll have to take care that
- you write at least the basic entries for the sections:
-
- ibendinterface
- ibenddefs
- ibendsyms
- ibendbrowser (only when you've set uf_has_browser!)
- ibendimplementation
- ibend
-
- 75
-
-
-
- APPENDIX A. ANATOMY OF A UNIT FILE A.5. CREATING PPUFILES
-
-
- Writing an entry is a little di erent than reading it. You need to first put everything
- in the entry with ppufile.putxxx:
-
- procedure putdata(var b;len:longint);
- procedure putbyte(b:byte);
- procedure putword(w:word);
- procedure putlongint(l:longint);
- procedure putreal(d:ppureal);
- procedure putstring(s:string);
-
- After putting all the things in the entry you need to call ppufile.writeentry(ibnr:byte)
- where ibnr is the entry number you're writing.
- At the end of the file you need to call ppufile.writeheader to write the new
- header to the file. This takes automatically care of the new size of the ppufile.
- When that is also done you can call ppufile.close and dispose the object.
- Extra functions/variables available for writing are:
-
- ppufile.NewHeader;
- ppufile.NewEntry;
-
- This will give you a clean header or entry. Normally called automatically in
- ppufile.writeentry, so you can't forget it.
-
- ppufile.flush;
-
- to flush the current bu ers to the disk
-
- ppufile.do_crc:boolean;
-
- set to false if you don't want that the crc is updated, this is necessary if you write
- for example the browser data.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 76
-
-
-
- Appendix B
-
- Compiler and RTL source
- tree structure
-
- B.1 The compiler source tree
-
- All compiler source files are in one directory, normally in source/compiler. For more
- informations about the structure of the compiler have a look at the Compiler Manual
- which contains also some informations about compiler internals.
- The compiler directory contains a subdirectory utils, which contains mainly the
- utilities for creation and maintainance of the message files.
-
-
- B.2 The RTL source tree
-
- The RTL source tree is divided in many subdirectories, but is very structured and
- easy to understand. It mainly consists of three parts:
-
- 1. A OS-dependent directory. This contains the files that are di erent for each
- operating system. When compiling the RTL, you should do it here. The
- following directories exist:
-
- * atari for the atari. Not maintained any more.
- * amiga for the amiga. Not maintained any more.
- * go32v1 For dos, using the GO32v1 extender. Not maintained any more.
- * go32v2 For dos, using the GO32v2 extender.
- * linux for linux platforms. It has two subdirect
- * os2 for os/2.
- * win32 for Win32 platforms.
-
- 2. A processor dependent directory. This contains files that are system indepen-
- dent, but processor dependent. It contains mostly optimized routines for a
- specific processor. The following directories exist:
-
- * i386 for the Intel series of processors.
- * m68k for the motorola m68000 series of processors.
-
-
- 77
-
-
-
- APPENDIX B. COMPILER AND RTL SOURCE TREE
- B.2. STR
- THE R UCTURE
- TL SOURCE TREE
-
-
- 3. An OS-independent and Processor independent directory: inc. This contains
- complete units, and include files containing interface parts of units.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 78
-
-
-
- Appendix C
-
- Compiler limits
-
- Although many of the restrictions imposed by the MS-DOS system are removed
- by use of an extender, or use of another operating system, there still are some
- limitations to the compiler:
-
- 1. Procedure or Function definitions can be nested to a level of 32.
-
- 2. Maximally 255 units can be used in a program when using the real-mode
- compiler (i.e. a binary that was compiled by Borland Pascal). When using
- the 32-bit compiler, the limit is set to 1024. You can change this by redefining
- the maxunits constant in the files.pas compiler source file.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 79
-
-
-
- Appendix D
-
- Compiler modes
-
- Here we list the exact e ect of the di erent compiler modes. They can be set with
- the $Mode switch, or by command line switches.
-
-
- D.1 FPC mode
-
- This mode is selected by the $MODE FPC switch. On the command-line, this means
- that you use none of the other compatibility mode switches. It is the default mode
- of the compiler. This means essentially:
-
- 1. You must use the address operator to assign procedural variables.
-
- 2. A forward declaration must be repeated exactly the same by the implementa-
- tion of a function/procedure. In particular, you can not omit the parameters
- when implementing the function or procedure.
-
- 3. Overloading of functions is allowed.
-
- 4. Nested comments are allowed.
-
- 5. The Objpas unit is NOT loaded.
-
- 6. You can use the cvar type.
-
- 7. PChars are converted to strings automatically.
-
-
- D.2 TP mode
-
- This mode is selected by the $MODE TP switch. On the command-line, this mode is
- selected by the -So switch.
-
- 1. You cannot use the address operator to assign procedural variables.
-
- 2. A forward declaration must not be repeated exactly the same by the imple-
- mentation of a function/procedure. In particular, you can omit the parameters
- when implementing the function or procedure.
-
- 3. Overloading of functions is not allowed.
-
- 4. The Objpas unit is NOT loaded.
-
- 80
-
-
-
- APPENDIX D. COMPILER MODES D.3. DELPHI MODE
-
-
- 5. Nested comments are not allowed.
-
- 6. You can not use the cvar type.
-
-
- D.3 Delphi mode
-
- This mode is selected by the $MODE DELPHI switch. On the command-line, this
- mode is selected by the -Sd switch.
-
- 1. You can not use the address operator to assign procedural variables.
-
- 2. A forward declaration must not be repeated exactly the same by the im-
- plementation of a function/procedure. In particular, you can not omit the
- parameters when implementing the function or procedure.
-
- 3. Overloading of functions is not allowed.
-
- 4. Nested comments are not allowed.
-
- 5. The Objpas unit is loaded right after the system unit. One of the consequences
- of this is that the type Integer is redefined as Longint.
-
-
- D.4 GPC mode
-
- This mode is selected by the $MODE GPC switch. On the command-line, this mode
- is selected by the -Sp switch.
-
- 1. You must use the address operator to assign procedural variables.
-
- 2. A forward declaration must not be repeated exactly the same by the imple-
- mentation of a function/procedure. In particular, you can omit the parameters
- when implementing the function or procedure.
-
- 3. Overloading of functions is not allowed.
-
- 4. The Objpas unit is NOT loaded.
-
- 5. Nested comments are not allowed.
-
- 6. You can not use the cvar type.
-
-
- D.5 OBJFPC mode
-
- This mode is selected by the $MODE OBJFPC switch. On the command-line, this
- mode is selected by the -S2 switch.
-
- 1. You must use the address operator to assign procedural variables.
-
- 2. A forward declaration must be repeated exactly the same by the implementa-
- tion of a function/procedure. In particular, you can not omit the parameters
- when implementing the function or procedure.
-
- 3. Overloading of functions is allowed.
-
- 4. Nested comments are allowed.
-
- 81
-
-
-
- APPENDIX D. COMPILER MODES D.5. OBJFPC MODE
-
-
- 5. The Objpas unit is loaded right after the system unit. One of the consequences
- of this is that the type Integer is redefined as Longint.
-
- 6. You can use the cvar type.
-
- 7. PChars are converted to strings automatically.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 82
-
-
-
- Appendix E
-
- Using makefile.fpc
-
- E.1 Introduction
-
- Free Pascal comes with a special makefile, makefile.fpc, which can be included in any
- makefile you use to compile with Free Pascal. There is a template Makefile provided
- also. All sources from the Free Pascal team are compiled with this system.
- These files are installed in the following directories:
-
- linux
-
- Dos or Windows
-
- The template Makefile searches for the makefile.fpc in the following places :
-
- 1. The file pointed to by the FPCMAKE environment variable.
-
- 2. The directory pointed to by the FPCDIR envinonment variable.
-
- 3. The directory pointed to by the DEFAULTFPCDIR make variable.
-
- 4. The current directory.
-
- Thus, setting FPCMAKE or FPCDIR as an environment string will ensure that make-
- file.fpc is always found, and will be read by all makefiles, derived from the template.
- The following sections explain what variables are set by makefile.fpc, what vari-
- ables it expects to be set, and what targets it defines. After that, some settings in
- the template makefile are explained.
-
-
- E.2 Programs needed to use the makefile
-
- The following programs are needed by the makefile to function correctly:
-
- cp a copy program.
-
- date a program that prints the date.
-
- install a program to install files.
-
- make the make program, obviously.
-
- 83
-
-
-
- APPENDIX E. USING MAKEFILE.FPC
- E.3. VARIABLES USED BY MAKEFILE.FPC
-
-
- pwd a program that prints the current working directory.
-
- rm a program to delete files.
-
- These are standard programs on linux systems, with the possible exception of make.
- For dos or Windows NT, they can be found in the file gnuutils.zip on the Free
- Pascal FTP site.
-
-
- E.3 Variables used by makefile.fpc
-
- Many variables a ect the behaviour of the makefile. The variables can be split in
- several groups:
-
- Required variables
-
- Directory variables
-
- Target variables
-
- Compiler command-line variables
-
- Each group will be discussed separately in the subsequent.
-
-
- Required variables
- In principle, the makefile.fpc only expects one variable to be set:
-
- FPCDIR This is the base directory of Free Pascal sources. The makefile expects
- to find a directory rtl below this directory.
-
-
- Directory variables
- The first set of variables controls the directories used in the makefile:
-
- INC this is a list of directories, separated by spaces, that will be added as include
- directories to the compiler command-line.
-
- LIBDIR is a list of library paths, separated by spaces. Each directory in the list
- is prepended with -Fl and added to the compiler options.
-
- NEEDLIBDIR is a space-separated list of library paths. Each directory in the
- list is prepended with -Fl and added to the compiler options.
-
- NEEDOBJDIR is a list of object file directories, separated by spaces. Each
- directory in the list is prepended with -Fo and added to the compiler options.
-
- NEEDUNITDIR is a list of unit directories, separated by spaces. Each directory
- in the list is prepended with -Fu and is added to the compiler options.
-
- OBJDIR is a list of object file directories, separated by spaces, that is added to
- the object files path, i.e. Each directory in the list is prepended with -Fo.
-
- OSINC this is a space-separated list of OS-dependent directories that will be added
- as include directories to the compiler command line.
-
-
- 84
-
-
-
- APPENDIX E. USING MAKEFILE.FPC
- E.3. VARIABLES USED BY MAKEFILE.FPC
-
-
- PROCINC is a space-separated list of processor-dependent directories that will
- be added as include directories to the compiler command-line.
-
- RTL If RTLDIR is not set, RTL is used to construct RTLDIR, after which RTLDIR is
- added to the compiler unit path, with -Fu prepended. If RTLDIR is not set, it
- is set to $(RTL)/$(OS TARGET).
-
- RTLDIR Directory where the RTL unit sources are. If RTLDIR is not set, it is set
- to $(RTL)/$(OS TARGET).
- If RTL is also not set, it is set to $(FPCDIR)/rtl/$(OS TARGET).
-
- TARGETDIR If set, this directory is added as the output directory of the com-
- piler, where all units and executables are written, i.e. it gets -FE prepended.
-
- UNIT If UNITDIR is not set, UNIT is used to construct UNITDIR. UNITDIR is added
- to the compiler unit path, with -Fu prepended.
-
- UNITDIR Directory where the RTL compiled units are. If UNITDIR is not set, it
- is set to $(UNIT)/$(OS TARGET).
- If UNIT is also not set, it is set to $(FPCDIR)/rtl/$(OS TARGET).
-
- UNITS The content of this variable are appended to the BASEINSTALLDIR variable
- to install the units.
-
- UNITTARGETDIR If set, this directory is added as the output directory of
- the compiler, where all units are written, i.e. it gets -FU prepended. This
- overrides TARGETDIR.
-
-
- Target variables
- The second set of variables controls the targets that are constructed by the makefile:
-
- DEFAULTUNITS If defined, only units will be made by the makefile. If not
- defined, then executables are made also.
-
- EXEOBJECTS This is a list of executable names that will be compiled. the
- makefile appends $(EXEEXT) to these names.
-
- LOADEROBJECTS is a list of space-separated names that identify loaders to
- be compiled. This is mainly used in the compiler's RTL sources.
-
- UNITOBJECTS This is a list of unit names that will be compiled. The makefile
- appends $(PPUEXT) to each of these names to form the unit file name. The
- sourcename is formed by adding $(PASEXT).
-
- ZIPNAME is the name of the archive that will be created by the makefile.
-
- ZIPTARGET is the target that is built before the archive is made. this target is
- built first. If successful, the zip archive will be made.
-
-
- Compiler command-line variables
- The following variables control the compiler command-line:
-
- CFGFILE if this variable is set, it will be used as the name of the config file to
- be used by the compiler.
-
-
- 85
-
-
-
- APPENDIX E. USING MAKEFILE.FPC
- E.4. VARIABLES SET BY MAKEFILE.FPC
-
-
- CPU the CPU type is added as a define to the compiler command line. Automat-
- ically determined by the makefile.
-
- LIBNAME if smartlinking is requested (i.e. SMARTLINK is set to YES), this is the
- name of the static library to produce. Don't add lib to this, the compiler
- will do that.
-
- LIBTYPE if set to shared, then the compiler will emit a shared library, with
- name LIBNAME.If LIBTYPE is set to static, the compiler will emit a static,
- smartlinked library,
-
- NEEDGCCLIB if this variable is defined, then the path to libgcc is added to the
- library path.
-
- NEEDOTHERLIB (linux only) If this is defined, then the makefile will append
- all directories that appear in /etc/ld.so.conf to the library path.
-
- OPT Any options that you want to pass to the compiler. The contents of OPT is
- simply added to the compiler command-line.
-
- OPTDEF Are optional defines, added to the command-line of the compiler. They
- do not get -d prepended.
-
- OS TARGET What platform you want to compile for. Added to the compiler
- command-line with a -T prepended.
-
- SMARTLINK if SMARTLINK is set to YES then the compiler will output smartlinked
- units if LIBTYPE is not set to shared.
-
-
- E.4 Variables set by makefile.fpc
-
- All of the following variables are only set by makefile.fpc, if they aren't already
- defined. This means that you can override them by setting them on the make
- command line, or setting them in the makefile you use, BEFORE makefile.fpc is
- included. The following sets of variables are defined:
-
- Directory variables
-
- Program names
-
- File extensions item[Target files]
-
- Each of these sets is discussed in the subsequent:
-
-
- Directory variables
- The following directories are defined by the makefile:
-
- BASEDIR is set to the current directory if the pwd command is available. If not,
- it is set to '.'.
-
- BASEINSTALLDIR is the base for all directories where units are installed. On
- linux, this is set to $(PREFIXINSTALLDIR)/lib/fpc/$(RELEASEVER).
- On other systems, it is set to $(PREFIXINSTALLDIR)
-
-
-
- 86
-
-
-
- APPENDIX E. USING MAKEFILE.FPC
- E.4. VARIABLES SET BY MAKEFILE.FPC
-
-
- BININSTALLDIR is set to $(BASEINSTALLDIR)/bin on linux, and
- $(BASEINSTALLDIR)/bin/$(OS TARGET) on other systems. This is the place
- where binaries are installed.
-
- GCCLIBDIR (linux only) is set to the directory where libgcc.a is.
-
- LIBINSTALLDIR is set to $(BASEINSTALLDIR) on linux,
- and $(BASEINSTALLDIR)/lib on other systems.
-
- OTHERLIBDIR (linux only) is set to the full set of paths in /etc/ld.so.conf
-
- PREFIXINSTALLDIR is set to /usr on linux, /pp on dos or Windows NT.
-
- SHARED LIBINSTALLDIR is where shared libraries are installed. This equals
- $(PREFIXINSTALLDIR)/lib on linux, and SHARED UNITINSTALLDIR on other
- systems.
-
- SHARED UNITINSTALLDIR is where units from libraries are installed. This
- equals $(UNITINSTALLDIR)/shared
-
- STATIC LIBINSTALLDIR is where static libraries will be installed. By de-
- fault, it equals $(STATIC UNITINSTALLDIR).
-
- STATIC UNITINSTALLDIR is where static, smartlinked units will be installed.
- It equals $(UNITINSTALLDIR)/static.
-
- UNITINSTALLDIR is where units will be installed. This is set to
- $(BASEINSTALLDIR)/$(UNITPREFIX)
- on linux. On other systems, it is set to
- $(BASEINSTALLDIR)/$(UNITPREFIX)/$(OS TARGET).
-
-
- Program names
- The following variables are program names, used in makefile targets.
-
- AS The assembler. Default set to as.
-
- COPY a file copy program. Default set to cp -fp.
-
- CMP a program to compare files. Default set to cmp.
-
- DEL a file removal program. Default set to rm -f.
-
- DELTREE a directory removal program. Default set to rm -rf.
-
- DATE a program to display the date.
-
- DIFF a program to produce di files.
-
- ECHO an echo program.
-
- INSTALL a program to install files. Default set to install -m 644 on linux.
-
- INSTALLEXE a program to install executable files. Default set to install -m 755
- on linux.
-
- LD The linker. Default set to ld.
-
- LDCONFIG (linux only) the program used to update the loader cache.
-
-
- 87
-
-
-
- APPENDIX E. USING MAKEFILE.FPC
- E.4. VARIABLES SET BY MAKEFILE.FPC
-
-
- MKDIR a program to create directories if they don't exist yet. Default set to
- install -m 755 -d
-
- MOVE a file move program. Default set to mv -f
-
- PP the Free Pascal compiler executable. Default set to ppc386.exe
-
- PPAS the name of the shell script created by the compiler if the -s option is
- specified. This command will be executed after compilation, if the -s option
- was detected among the options.
-
- PPUMOVE the program to move units into one big unit library.
-
- SED a stream-line editor program. Default set to sed.
-
- UPX an executable packer to compress your executables into self-extracting com-
- pressed executables.
-
- ZIPEXE a zip program to compress files. zip targets are made with this program
-
-
- File extensions
- The following variables denote extensions of files. These variables include the .
- (dot) of the extension. They are appended to object names.
-
- ASMEXT is the extension of assembler files produced by the compiler.
-
- LOADEREXT is the extension of the assembler files that make up the executable
- startup code.
-
- OEXT is the extension of the object files that the compiler creates.
-
- PACKAGESUFFIX is a su x that is appended to package names in zip targets.
- This serves so packages can be made for di erent OSes.
-
- PASEXT is the extension of pascal files used in the compile rules. It is determined
- by looking at the first EXEOBJECTS source file or the first UNITOBJECTS files.
-
- PPLEXT is the extension of shared library unit files.
-
- PPUEXT is the extension of default units.
-
- SHAREDLIBEXT is the extension of shared libraries.
-
- SMARTEXT is the extension of smartlinked unit assembler files.
-
- STATICLIBEXT is the extension of static libraries.
-
-
- Target files
- The following variables are defined to make targets and rules easier:
-
- COMPILER is the complete compiler commandline, with all options added, after
- all Makefile variables have been examined.
-
- DATESTR contains the date.
-
- EXEFILES is a list of executables that will be created by the makefile.
-
-
- 88
-
-
-
- APPENDIX E. USING
- E.5. MAKEFILE.FPC
- RULES AND TARGETS CREATED BY MAKEFILE.FPC
-
-
- EXEOFILES is a list of executable object files that will be created by the makefile.
-
- LOADEROFILES is a list of object files that will be made from the loader as-
- sembler files. This is mainly for use in the compiler's RTL sources.
-
- UNITFILES a list of unit files that will be made. This is just the list of unit
- objects, with the correct unit extension appended.
-
- UNITOFILES a list of unit object files that will be made. This is just the list of
- unit objects, with the correct object file extension appended.
-
-
- E.5 Rules and targets created by makefile.fpc
-
- The makefile.fpc defines a series of targets, which can be called by your own
- targets. They have names that resemble default names (such as 'all', 'clean'), only
- they have fpc prepended.
-
-
- Pattern rules
- The makefile makes the following pattern rules:
-
- units how to make a pascal unit form a pascal source file.
-
- executables how to make an executable from a pascal source file.
-
- object file how to make an object file from an assembler file.
-
-
- Build rules
- The following build targets are defined:
-
- fpc all target that builds all units and executables as well as loaders. If DEFAULTUNITS
- is defined, executables are excluded from the targets.
-
- fpc exes target to make all executables in EXEOBJECTS.
-
- fpc loaders target to make all files in LOADEROBJECTS.
-
- fpc sharedlib target that makes all units as dynamic libraries.
-
- fpc staticlib target that makes all units as smartlinked units.
-
- fpc units target to make all units in UNITOBJECTS.
-
-
- Cleaning rules
- The following cleaning targets are defined:
-
- fpc clean cleans all files that result when fpc all was made.
-
- fpc libsclean is the same as fpc clean, but also removes any shared or dynamic
- libraries that may have been built.
-
- fpc cleanall is the same as both previous target commands, but also deletes all
- object, unit and assembler files that are present.
-
-
- 89
-
-
-
- APPENDIX E. USING MAKEFILE.FPC
- E.6. USING THE PROVIDED TEMPLATE
-
-
- archiving rules
- The following archiving targets are defined:
-
- fpc zipinstalladd will add to a (possibibly existing) archive file (it's name is taken
- from $(ZIPNAME).
-
- fpc zipinstall is the same, only the archive is cleared first.
-
- The zip is made uzing the ZIPEXE program. Under linux, a .tar.gz file is created.
-
-
- Informative rules
- The following targets produce information about the makefile:
-
- fpc cfginfo gives general configuration information: the location of the makefile,
- the compiler version, target OS, CPU.
-
- fpc dirinfo gives the directories, used by the compiler.
-
- fpc info executes all other info targets.
-
- fpc installinfo gives all directories where files will be installed.
-
- fpc objectinfo lists all objects that will be made.
-
- fpc toolsinfo lists all defined tools.
-
-
- E.6 Using the provided template
-
- The template makefile that comes with Free Pascal does nothing other than of-
- fering you some variables to be set for the makefile.fpc. After that it loads the
- makefile.fpc in the indicated places.
- Finally it declares a set of default targets:
-
- all calls fpc all.
-
- clean calls fpc clean.
-
- install calls fpc install.
-
- info calls fpc info.
-
- staticlib calls fpc staticlib.
-
- sharedlib calls fpc sharedlib.
-
- libsclean calls fpc libsclean.
-
- staticinstall calls fpc staticinstall.
-
- sharedinstall calls fpc sharedinstall.
-
- libinstall calls fpc libinstall.
-
- You can override each of these targets to suit your setup.
- If you just have to compile some units and programs, you only need to set the
- following variables:
-
- 90
-
-
-
- APPENDIX E. USING MAKEFILE.FPC
- E.6. USING THE PROVIDED TEMPLATE
-
-
- UNITOBJECTS names of units you wish to be built.
-
- EXEOBJECTS names of executables you wish to be built.
-
- You may want to set some of the following variables:
-
- INC,PROCINC or OSINC To indicate where include files can be found.
-
- NEEDOPT additional options added to the compile command.
-
- NEEDUNITDIR space-separated list of directories where units that you need
- are located.
-
- TARGETDIR,UNITTARGETDIR where do you want executables and units
- to be written. Be aware that setting this variable may interfere with make,
- since it will not find the target files.
-
- DEFAULTUNITS if you define this variable (to whatever value you want) then
- the all target will by default only make the units.
-
- You may also set any of the variables that appear in the previous sections, to
- override default behaviour of the makefile.
- After having set these variables, you can run 'make info' to see whether all variables
- are set to you satisfaction. If the makefile.fpc is not found, this command will inform
- you of this.
- After that, a simple 'make all' will make all units and executables.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 91
-
-
-
- Appendix F
-
- Compiling the compiler
- yourself
-
- F.1 Introduction
-
- The Free Pascal team releases at intervals a completely prepared package, with
- compiler and units all ready to use, the so-called releases. After a release, work
- on the compiler continues, bugs are fixed and features are added. The Free Pascal
- team doesn't make a new release whenever they change something in the compiler,
- instead the sources are available for anyone to use and compile. Compiled versions
- of RTL and compiler are also made daily, and put on the web.
- There are, nevertheless, circumstances when you'll want to compile the compiler
- yourself. For instance if you made changes to compiler code, or when you download
- the compiler via CVS.
- There are essentially 2 ways of recompiling the compiler: by hand, or using the
- makefiles. Each of these methods will be discussed.
-
-
- F.2 Before you begin
-
- To compile the compiler easily, it is best to keep the following directory structure
- (a base directory of /pp/src is supposed, but that may be di erent):
-
- /pp/src/Makefile
- /makefile.fpc
- /rtl/linux
- /inc
- /i386
- /...
- /compiler
-
- If you want to use the makefiles, you must use the above directory tree.
- The compiler and rtl source are zipped in such a way that if you unzip both files in
- the same directory (/pp/src in the above) the above directory tree results.
- The makefile.fpc and Makefile come from the base.zip file on the ftp site. If you
- compile manually, you don't need them.
-
-
- 92
-
-
-
- APPENDIX F. COMPILING THE COMPILER YOURSELF
- F.3. COMPILING USING MAKE
-
-
- There are 2 ways to start compiling the compiler and RTL. Both ways must be
- used, depending on the situation. Usually, the RTL must be compiled first, before
- compiling the compiler, after which the compiler is compiled using the current com-
- piler. In some special cases the compiler must be compiled first, with a previously
- compiled RTL.
- How to decide which should be compiled first? In general, the answer is that you
- should compile the RTL first. There are 2 exceptions to this rule:
-
- 1. The first case is when some of the internal routines in the RTL have changed,
- or if new internal routines appeared. Since the OLD compiler doesn't know
- about these changed internal routines, it will emit function calls that are based
- on the old compiled RTL, and hence are not correct. Either the result will
- not link, or the binary will give errors.
- 2. The second case is when something is added to the RTL that the compiler
- needs to know about (a new default assembler mechanism, for example).
-
- How to know if one of these things has occurred ? There is no way to know, except
- by mailing the Free Pascal team. If you cannot recompile the compiler when you
- first compile the RTL, then try the other way.
-
-
- F.3 Compiling using make
-
- When compiling with make it is necessary to have the above directory structure.
- Compiling the compiler is achieved with the target cycle.
- Under normal circumstances, recompiling the compiler is limited to the following
- instructions (assuming you start in directory /pp/src):
-
- cd compiler
- make cycle
-
- This will work only if the makefile.fpc is installed correctly and if the needed tools
- are present in the PATH. Which tools must be installed can be found in appendix E.
- The above instructions will do the following:
-
- 1. Using the current compiler, the RTL is compiled in the correct directory,
- which is determined by the OS you are under. e.g. under linux, the RTL is
- compiled in directory rtl/linux.
- 2. The compiler is compiled using the newly compiled RTL. If successful, the
- newly compiled compiler executable is copied to a temporary executable.
- 3. Using the temporary executable from the previous step, the RTL is re-compiled.
- 4. Using the temporary executable and the newly compiled RTL from the last
- step, the compiler is compiled again.
-
- The last two steps are repeated 3 times, until three passes have been made or until
- the generated compiler binary is equal to the binary it was compiled with. This
- process ensures that the compiler binary is correct.
- Compiling for another target: When you want to compile the compiler for another
- target, you must specify the OS TARGET makefile variable. It can be set to the
- following values: win32, go32v2, os2 and linux. As an example, cross-compilation
- for the go32v2 target from the win32 target is chosen:
-
- 93
-
-
-
- APPENDIX F. COMPILING THE COMPILER YOURSELF
- F.4. COMPILING BY HAND
-
-
- cd compiler
- make cycle OS_TARGET=go32v2
-
- This will compile the go32v2 RTL, and compile a go32v2 compiler.
- If you want to compile a new compiler, but you want the compiler to be compiled
- first using an existing compiled RTL, you should specify the all target, and specify
- another RTL directory than the default (which is the ../rtl/$(OS TARGET) direc-
- tory). For instance, assuming that the compiled RTL units are in /pp/rtl, you
- could type
-
- cd compiler
- make clean
- make all UNITDIR=/pp/rtl
-
- This will then compile the compiler using the RTL units in /pp/rtl. After this has
- been done, you can do the 'make cycle', starting with this compiler:
-
- make cycle PP=./ppc386
-
- This will do the make cycle from above, but will start with the compiler that was
- generated by the make all instruction.
- In all cases, many options can be passed to make to influence the compile process.
- In general, the makefiles add any needed compiler options to the command-line, so
- that the RTL and compiler can be compiled. You can specify additional options
- (e.g. optimization options) by passing them in OPT.
-
-
- F.4 Compiling by hand
-
- Compiling by hand is di cult and tedious, but can be done. We'll treat the com-
- pilation of RTL and compiler separately.
-
-
- Compiling the RTL
- To recompile the RTL, so a new compiler can be built, at least the following units
- must be built, in the order specified:
-
- loaders the program stubs, that are the startup code for each pascal program. These
- files have the .as extension, because they are written in assembler. They must
- be assembled with the gnu as assembler. These stubs are in the OS-dependent
- directory, except for linux, where they are in a processor dependent subdi-
- rectory of the linux directory (i386 or m68k).
-
- system the system unit. This unit is named di erently on di erent systems:
-
- * Only on GO32v2, it's called system.
- * For linux it's called syslinux.
- * For Windows NT it's called syswin32.
- * For os/2 it's called sysos2
-
- This unit resides in the OS-dependent subdirectories of the RTL.
-
- strings The strings unit. This unit resides in the inc subdirectory of the RTL.
-
- 94
-
-
-
- APPENDIX F. COMPILING THE COMPILER YOURSELF
- F.4. COMPILING BY HAND
-
-
- dos The dos unit. It resides in the OS-dependent subdirectory of the RTL. Possibly
- other units will be compiled as a consequence of trying to compile this unit
- (e.g. on linux, the linux unit will be compiled, on go32, the go32 unit will be
- compiled).
-
- objects the objects unit. It resides in the inc subdirectory of the RTL.
-
- To compile these units on a i386, the following statements will do:
-
- ppc386 -Tlinux -b- -Fi../inc -Fi../i386 -FE. -di386 -Us -Sg syslinux.pp
- ppc386 -Tlinux -b- -Fi../inc -Fi../i386 -FE. -di386 ../inc/strings.pp
- ppc386 -Tlinux -b- -Fi../inc -Fi../i386 -FE. -di386 dos.pp
- ppc386 -Tlinux -b- -Fi../inc -Fi../i386 -FE. -di386 ../inc/objects.pp
-
- These are the minimum command-line options, needed to compile the RTL.
- For another processor, you should change the i386 into the appropriate proces-
- sor. For another operating system (target) you should change the syslinux in the
- appropriate system unit file, and you should change the target OS setting (-T).
- Depending on the target OS there are other units that you may wish to compile,
- but which are not strictly needed to recompile the compiler. The following units
- are available for all plaforms:
-
- objpas Needed for Delphi mode. Needs -S2 as an option. Resides in the objpas
- subdirectory.
-
- sysutils many utility functions, like in Delphi. Resides in the objpas directory, and
- needs -S2 to compile.
-
- typinfo functions to access RTTI information, like Delphi. Resides in the objpas
- directory.
-
- math math functions like in Delphi. Resides in the objpas directory.
-
- mmx extensions for MMX class Intel processors. Resides in in the i386 directory.
-
- getopts a GNU compatible getopts unit. resides in the inc directory.
-
- heaptrc to debug the heap. resides in the inc directory.
-
-
- Compiling the compiler
- Compiling the compiler can be done with one statement. It's always best to remove
- all units from the compiler directory first, so something like
-
- rm *.ppu *.o
-
- on linux, and on dos
-
- del *.ppu
- del *.o
-
- After this, the compiler can be compiled with the following command-line:
-
- ppc386 -Tlinux -Fu../rtl/linux -di386 -dGDB pp.pas
-
- So, the minimum options are:
-
- 95
-
-
-
- APPENDIX F. COMPILING THE COMPILER YOURSELF
- F.4. COMPILING BY HAND
-
-
-
- Table F.1: Possible defines when compiling FPC
-
- Define does what
- USE RHIDE Generates errors and warnings in a format recognized
- by RHIDE.
- TP Needed to compile the compiler with Turbo or Borland Pascal.
- Delphi Needed to compile the compiler with Delphi from Borland.
- GDB Support of the GNU Debugger.
- I386 Generate a compiler for the Intel i386+ processor family.
- M68K Generate a compiler for the M68000 processor family.
- USEOVERLAY Compiles a TP version which uses overlays.
- EXTDEBUG Some extra debug code is executed.
- SUPPORT MMX only i386: enables the compiler switch MMX which
- allows the compiler to generate MMX instructions.
- EXTERN MSG Don't compile the msgfiles in the compiler, always use
- external messagefiles (default for TP).
- NOAG386INT no Intel Assembler output.
- NOAG386NSM no NASM output.
- NOAG386BIN leaves out the binary writer.
-
-
- 1. The target OS. Can be skipped if you're compiling for the same target as the
- compiler you're using.
-
- 2. A path to an RTL. Can be skipped if a correct ppc386.cfg configuration is on
- your system. If you want to compile with the RTL you compiled first, this
- should be ../rtl/OS (replace the OS with the appropriate operating system
- subdirectory of the RTL).
-
- 3. A define with the processor you're compiling for. Required.
-
- 4. -dGDB is not strictly needed, but is better to add since otherwise you won't
- be able to compile with debug information.
-
- 5. -Sg is needed, some parts of the compiler use goto statements (to be specific:
- the scanner).
-
- So the absolute minimal command line is
-
- ppc386 -di386 -Sg pp.pas
-
- You can define some other command-line options, but the above are the minimum.
- A list of recognised options can be found in table (F.1).
- This list may be subject to change, the source file pp.pas always contains an up-to-
- date list.
-
-
-
-
-
-
-
-
-
- 96
-
-
-
-