1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410 |
- %
- % $Id$
- % This file is part of the FPC documentation.
- % Copyright (C) 1997, by Michael Van Canneyt
- %
- % The FPC documentation is free text; you can redistribute it and/or
- % modify it under the terms of the GNU Library General Public License as
- % published by the Free Software Foundation; either version 2 of the
- % License, or (at your option) any later version.
- %
- % The FPC Documentation is distributed in the hope that it will be useful,
- % but WITHOUT ANY WARRANTY; without even the implied warranty of
- % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- % Library General Public License for more details.
- %
- % You should have received a copy of the GNU Library General Public
- % License along with the FPC documentation; see the file COPYING.LIB. If not,
- % write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- % Boston, MA 02111-1307, USA.
- %
- \documentclass{report}
- \usepackage{a4}
- \usepackage{html}
- \latex{\usepackage{multicol}}
- \latex{\usepackage{fpcman}}
- \html{\input{fpc-html.tex}}
- % define the version number here, and not in the fpc.sty !!!
- \newcommand{\remark}[1]{\par$\rightarrow$\textbf{#1}\par}
- \newcommand{\olabel}[1]{\label{option:#1}}
- % We should change this to something better. See \seef etc.
- \begin{document}
- \title{Free Pascal \\ Programmers' manual}
- \docdescription{Programmers' manual for \fpc, version \fpcversion}
- \docversion{1.3}
- \date{March 1998}
- \author{Micha\"el Van Canneyt}
- \maketitle
- \tableofcontents
- \newpage
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Introduction
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \section*{About this document}
- This is the programmer's manual for \fpc.
- It describes some of the peculiarities of the \fpc compiler, and provides a
- glimp 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 \userref). 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 \refref)
- 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 me\footnote{at
- \var{[email protected]}}.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Compiler switches
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Compiler directives}
- \label{ch:CompSwitch}
- \fpc 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 effect from the moment they are encountered, global directives have an
- effect on all of the compiled code.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Local switches
- \section{Local directives}
- \label{se:LocalSwitch}
- Local directives have no command-line counterpart. They influence the
- compiler's behaviour from the moment they're encountered until the moment
- another switch annihilates their behaviour, or the end of the unit or
- program is reached.
- \subsection{\var{\$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 :
- \begin{verbatim}
- {$F+}
- Procedure TestProc;
- begin
- Writeln ('Hello From TestProc');
- end;
- begin
- testProc
- end.
- \end{verbatim}
- Generates the following compiler output:
- \begin{verbatim}
- 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
- \end{verbatim}
- You can see that the verbosity level was set to display warnings.
- If you declare a function as \var{Far} (this has the same effect as setting it
- between \var{\{\$F+\}...\{\$F-\}} directives), the compiler also generates a
- warning :
- \begin{verbatim}
- testf.pp(3) Warning: FAR ignored
- \end{verbatim}
- The same story is true for procedures declared as \var{Near}. The warning
- displayed in that case is:
- \begin{verbatim}
- testf.pp(3) Warning: NEAR ignored
- \end{verbatim}
- \subsection{\var{\$I} : Input/Output checking}
- The \var{\{\$I-\}} directive tells the compiler not to generate input/output
- checking code in your program. If you compile using the \var{-Ci} compiler
- switch, the \fpc 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
- \var{IOResult} function to see if everything went without problems.
- Conversely, \var{\{\$I+\}} will turn error-checking back on, until another
- directive is encountered which turns it off 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:
- \begin{verbatim}
- ...
- assign (f,'file.txt');
- {$I-}
- rewrite (f);
- {$I+}
- if IOResult<>0 then
- begin
- Writeln ('Error opening file : "file.txt"');
- exit
- end;
- ...
- \end{verbatim}
- \subsection{\var{\$I} : Include file }
- The \var{\{\$I filename\}} directive tells the compiler to read further
- statements from the file \var{filename}. The statements read there will be
- inserted as if they occurred in the current file.
- The compiler will append the \file{.pp} extension to the file if you don't
- specify an extension 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 \fpc compiler.
- Contrary to Turbo Pascal, include files can cross blocks. I.e. you can start
- a block in one file (with a \var{Begin} keyword) and end it in another (with
- a \var{End} keyword). The smallest entity in an include file must be a token,
- i.e. an identifier, keyword or operator.
- \subsection{\var{\$L} : Link object file}
- The \var{\{\$L filename\}} directive tells the compiler that the file \file{filename}
- should be linked to your program. You can only use this directive in a
- program. If you do use it in a unit, the compiler will not complain, but
- simply ignores the directive.
- The compiler will {\em not} look for the file in the unit path.
- The name will be passed to the linker {\em exactly} as you've typed it.
- Since the files name is passed directly to the linker, this means that on
- \linux systems, the name is case sensitive, and must be typed exactly as it
- appears on your system.
- {\em 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 \var{ld} on th command line gives a list of formats
- \var{ld} knows about.
- You can pass other files and options to the linker using the \var{-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.
- % Assembler type
- \subsection{\var{\$I386\_XXX} : Specify assembler format}
- This switch informs the compiler what kind of assembler it can expect in an
- \var{asm} block. The \var{XXX} should be replaced by one of the following:
- \begin{description}
- \item [att\ ] Indicates that \var{asm} blocks contain AT\&T syntax assembler.
- \item [intel\ ] Indicates that \var{asm} blocks contain Intel syntax
- assembler.
- \item [direct\ ] Tells the compiler that asm blocks should be copied
- directly to the assembler file.
- \end{description}
- 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 \var{-R}.
- \subsection{\var{\$MMX} : MMX support}
- As of version 0.9.8, \fpc supports optimization for the \textbf{MMX} Intel
- processor (see also \ref{ch:MMXSupport}). This optimizes certain code parts for the \textbf{MMX} Intel
- processor, thus greatly improving speed. The speed is noticed mostly when
- moving large amounts of data. Things that change are
- \begin{itemize}
- \item Data with a size that is a multiple of 8 bytes is moved using the
- \var{movq} assembler instruction, which moves 8 bytes at a time
- \end{itemize}
- When \textbf{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 \textbf{MMX} support and clear the FPU using the \var{emms}
- function of the \file{cpu} unit.
- The following example will make this more clear:
- \begin{verbatim}
- Program MMXDemo;
- uses cpu;
- var
- d1 : 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.
- \end{verbatim}
- See, however, the chapter on MMX (\ref{ch:MMXSupport}) for more information
- on this topic.
- \subsection{\var{\$OUTPUT\_FORMAT} : Specify the output format}
- \var{\{\$OUTPUT\_FORMAT format\}} has the same functionality as the \var{-A}
- command-line option : It tells the compiler what kind of object file must be
- generated. You can specify this switch \textbf{only} befor the \var{Program}
- or \var{Unit} clause in your source file. The different kinds of formats are
- shown in \seet{Formats}.
- \begin{FPCltable}{ll}{Formats generated by the compiler}{Formats} \hline
- Switch value & Generated format \\ \hline
- att & AT\&T assembler file. \\
- o & Unix object file.\\
- obj & OMF file.\\
- wasm & assembler for the Watcom assembler. \\ \hline
- \end{FPCltable}
- \subsection{\var{\$V} : Var-string checking}
- When in the \var{+} state, the compiler checks that strings passed as
- parameters are of the same, identical, string type as the declared
- parameters of the procedure.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Global switches
- \section{Global directives}
- \label{se:GlobalSwitch}
- Global directives affect 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.
- \subsection{\var{\$A} : Align Data}
- This switch is recognized for Turbo Pascal Compatibility, but is not
- yet implemented. The alignment of data will be different in any case, since
- \fpc is a 32-bit compiler.
- \subsection{\var{\$B} : Complete boolean evaluation}
- This switch is understood by the \fpc compiler, but is ignored. The compiler
- 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 \var{Bofu}, which has a boolean
- result, will never get called.
- \begin{verbatim}
- If False and Bofu then
- ...
- \end{verbatim}
- \subsection{\var{\$D} : Debugging symbols}
- When this switch is on, the compiler inserts GNU debugging information in
- the executable. The effect of this switch is the same as the command-line
- switch \var{-g}. By default, insertion of debugging information is off.
- \subsection{\var{\$E} : Emulation of coprocessor}
- This directive controls the emulation of the coprocessor. On the i386
- processor, it is supported for
- compatibility with Turbo Pascal. The compiler itself doesn't do the emulation
- of the coprocessor. Under \dos, the \dos extender does this, and under
- \linux, the kernel takes care of the coprocessor support.
- If you use the Motorola 680x0 version, then the switch is recognized, as
- there is no extender to emulate the coprocessor, so the compiler must do
- that by itself.
- There is no command-line counterpart for this directive.
- \subsection{\var{\$G} : Generate 80286 code}
- This option is recognised for Turbo Pascal cmpatibility, but is ignored,
- because the compiler needs at least a 386 or higher class processor.
- \subsection{\var{\$L} : Local symbol information}
- This switch (not to be confused with the \var{\{\$L file\}} file linking
- directive) is recognised for Turbo Pascal compatibility, but is ignored.
- generation of symbol information is controlled by the \var{\$D} switch.
- \subsection{\var{\$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.
- \subsection{\var{\$O} : Overlay code generation }
- This switch is recognised for Turbo Pascal compatibility, but is otherwise
- ignored, since the compiler requires a 386 or higher computer, with at
- least 4 Mb. of ram.
- \subsection{\var{\$Q} : Overflow checking}
- The \var{\{\$Q+\}} directive turns on integer overflow checking.
- This means that the compiler inserts code to check for overflow when doing
- computations with an integer.
- When an overflow occurs, the run-time library will print a message
- \var{Overflow at xxx}, and exit the program with exit code 1.
- Using the \var{\{\$Q-\}} switch switches off the overflow checking code
- generation.
- The generation of overflow checking code can also be controlled
- using the \var{-Co} command line compiler option (see \userref).
- \subsection{\var{\$R} : Range checking}
- By default, the computer doesn't generate code to check the ranges of array
- indices, enumeration types, subrange types, etc. Specifying the
- \var{\{\$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 1.
- The \var{\{\$R-\}} 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.
- {\em Remark: } this has not been implemented completely yet.
- \subsection{\var{\$S} : Stack checking}
- The \var{\{\$S+\}} directive tells the compiler to generate stack checking
- code. This generates 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 1.
- Specifying \var{\{\$S-\}} will turn generation of stack-checking code off.
- There is no command-line switch which is equivalent to this directive.
- {\em Remark: } In principle, the stack is almost unlimited,
- i.e. limited to the total free amount of memory on the computer.
- \subsection{\var{\$X} : 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 off using the \var{\{\$X-\}} directive.
- The following, for instance, will not compile :
- \begin{verbatim}
- function Func (var Arg : sometype) : longint;
- begin
- ... { declaration of Func }
- end;
- ...
- {$X-}
- Func (A);
- \end{verbatim}
- The reason this construct is supported is that
- you may wish to call a function for certain side-effects 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 \var{-Sa1} has the same effect as the
- \var{\{\$X+\}} directive.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Using conditionals and macros
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Using conditionals, Messages and macros}
- \label{ch:CondMessageMacro}
- The \fpc 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.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Conditionals
- \section{Conditionals}
- \label{se:Conditionals}
- The rules for using conditional symbols are the same as under Turbo Pascal.
- Defining a symbol goes as follows:
- \begin{verbatim}
- {$Define Symbol }
- \end{verbatim}
- From this point on in your code, the compiler know the symbol \var{Symbol}
- Symbols are, like the Pascal language, case insensitive.
- You can also define a symbol on the command line. the \var{-dSymbol} option
- defines the symbol \var{Symbol}. You can specify as many symbols on the
- command line as you want.
- Undefining an existing symbol is done in a similar way:
- \begin{verbatim}
- {$Undef Symbol }
- \end{verbatim}
- 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 \verb|{$Undef ...}| statement.
- You can also undefine symbols from the command line with the \var{-u}
- command-line switch..
- To compile code conditionally, depending on whether a symbol is defined or
- not, you can enclose the code in a \verb|{$ifdef Symbol}| .. \verb|{$endif}|
- pair. For instance the following code will never be compiled :
- \begin{verbatim}
- {$Undef MySymbol}
- {$ifdef Mysymbol}
- DoSomething;
- ...
- {$endif}
- \end{verbatim}
- Similarly, you can enclose your code in a \verb|{$Ifndef Symbol}| .. \verb|{$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
- \var{DoSomething} will always be compiled:
- \begin{verbatim}
- {$Undef MySymbol}
- {$ifndef Mysymbol}
- DoSomething;
- ...
- {$endif}
- \end{verbatim}
- You can combine the two alternatives in one structure, namely as follows
- \begin{verbatim}
- {$ifdef Mysymbol}
- DoSomething;
- {$else}
- DoSomethingElse
- {$endif}
- \end{verbatim}
- In this example, if \var{MySymbol} exists, then the call to \var{DoSomething}
- will be compiled. If it doesn't exist, the call to \var{DoSomethingElse} is
- compiled.
- The \fpc compiler defines some symbols before starting to compile your
- program or unit. You can use these symbols to differentiate between
- different versions of the compiler, and between different compilers.
- In \seet{Symbols}, a list of pre-defined symbols is given\footnote{Remark:
- The \var{FPK} symbol is still defined for compatibility with older versions.}. In that table,
- you should change \var{v} with the version number of the compiler
- you're using, \var{r} with the release number and \var{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 \var{DOS}, \var{GO32V2},
- \var{LINUX}, \var{OS2} or \var{WIN32}. This symbol is undefined if you
- specify a target that is different from the platform you're compiling on.
- the \var{-TSomeOS} option on the command line will define the \var{SomeOS} symbol,
- and will undefined the existing platform symbol\footnote{In versions prior to
- 0.9.4, this didn't happen, thus making Cross-compiling impossible.}.
- \begin{FPCltable}{c}{Symbols defined by the compiler.}{Symbols} \hline
- Free \\
- VER\var{v} \\
- VER\var{v}\_\var{r} \\
- VER\var{v}\_\var{r}\_\var{p} \\
- OS \\ \hline
- \end{FPCltable}
- 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:
- \var{FPC}, \var{VER0}, \var{VER0\_9}, \var{VER0\_9\_1} and \var{LINUX}.
- Specifying \var{-TOS2} on the command-line will undefine the \var{LINUX}
- symbol, and will define the \var{OS2} symbol.
- {\em Remark: } Symbols, even when they're defined in the interface part of
- a unit, are not available outside that unit.
- \fpc supports the \var{\{\$IFOPT \}} directive for Turbo Pascal
- compatibility, but doesn't act on it. It always rejects the condition, so
- code between \var{\{\$IFOPT \}} and \var{\{\$Endif\}} is never compiled.
- Except for the Turbo Pascal constructs, from version 0.9.8 and higher,
- the \fpc compiler also supports a stronger conditional compile mechanism:
- The \var{\{\$If \}} construct.
- The prototype of this construct is as follows :
- \begin{verbatim}
- {$If expr}
- CompileTheseLines;
- {$else}
- BetterCompileTheseLines;
- {$endif}
- \end{verbatim}
- In this directive \var{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 numbers\footnote{Otherwise
- \var{\{\$If 8>54} would evaluate to \var{True}}.
- If the complemete expression evaluates to \var{'0'}, then it is considered
- false and rejected. Otherwise it is considered true and accepted. This may
- have unsexpected consequences :
- \begin{verbatim}
- {$If 0}
- \end{verbatim}
- Will evaluate to \var{False} and be rejected, while
- \begin{verbatim}
- {$If 00}
- \end{verbatim}
- Will evaluate to \var{True}.
- You can use any Pascal operator to construct your expression : \var{=, <>,
- >, <, >=, <=, 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:
- \begin{verbatim}
- {$ifdef fpc}
- var
- y : longint;
- {$else fpc}
- var
- z : longint;
- {$endif fpc}
- var
- x : longint;
- begin
- {$if (fpc_version=0) and (fpc_release>6) and (fpc_patch>4)}
- {$info At least this is version 0.9.5}
- {$else}
- {$fatalerror Problem with version check}
- {$endif}
- {$define x:=1234}
- {$if x=1234}
- {$info x=1234}
- {$else}
- {$fatalerror x should be 1234}
- {$endif}
- {$if 12asdf and 12asdf}
- {$info $if 12asdf and 12asdf is ok}
- {$else}
- {$fatalerror $if 12asdf and 12asdf rejected}
- {$endif}
- {$if 0 or 1}
- {$info $if 0 or 1 is ok}
- {$else}
- {$fatalerror $if 0 or 1 rejected}
- {$endif}
- {$if 0}
- {$fatalerror $if 0 accepted}
- {$else}
- {$info $if 0 is ok}
- {$endif}
- {$if 12=12}
- {$info $if 12=12 is ok}
- {$else}
- {$fatalerror $if 12=12 rejected}
- {$endif}
- {$if 12<>312}
- {$info $if 12<>312 is ok}
- {$else}
- {$fatalerror $if 12<>312 rejected}
- {$endif}
- {$if 12<=312}
- {$info $if 12<=312 is ok}
- {$else}
- {$fatalerror $if 12<=312 rejected}
- {$endif}
- {$if 12<312}
- {$info $if 12<312 is ok}
- {$else}
- {$fatalerror $if 12<312 rejected}
- {$endif}
- {$if a12=a12}
- {$info $if a12=a12 is ok}
- {$else}
- {$fatalerror $if a12=a12 rejected}
- {$endif}
- {$if a12<=z312}
- {$info $if a12<=z312 is ok}
- {$else}
- {$fatalerror $if a12<=z312 rejected}
- {$endif}
- {$if a12<z312}
- {$info $if a12<z312 is ok}
- {$else}
- {$fatalerror $if a12<z312 rejected}
- {$endif}
- {$if not(0)}
- {$info $if not(0) is OK}
- {$else}
- {$fatalerror $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.
- \end{verbatim}
- 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
- \sees{Macros}, they can be very useful. When trying this example, you must
- switch on macro support, with the \var{-Sm} command-line switch.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Macros
- \section{Messages}
- \label{se:Messages}
- \fpc lets you define normal, warning and error messages in your code.
- Messages 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 e displayed. Errors are always displayed, and the compiler
- stops as if an error had occurred.
- For messages, the syntax is as follows :
- \begin{verbatim}
- {$Message Message text }
- \end{verbatim}
- Or
- \begin{verbatim}
- {$Info Message text }
- \end{verbatim}
- For notes:
- \begin{verbatim}
- {$Note Message text }
- \end{verbatim}
- For warnings:
- \begin{verbatim}
- {$Warning Warning Message text }
- \end{verbatim}
- For errors :
- \begin{verbatim}
- {$Error Error Message text }
- \end{verbatim}
- Lastly, for fatal errors :
- \begin{verbatim}
- {$FatalError Error Message text }
- \end{verbatim}
- or
- \begin{verbatim}
- {$Stop Error Message text }
- \end{verbatim}
- The difference between \var{\$Error} and \var{\$FatalError} or \var{\$Stop}
- messages is that when the compiler encounters an error, it still continues
- to compile. With a fatal error, the compiler stops.
- {\em Remark :} You cannot use the '\var{\}}' 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 \var{RequiredVar} isn't defined:
- \begin{verbatim}
- {$ifndef RequiredVar}
- {$Error Requiredvar isn't defined !}
- {$endif}
- \end{verbatim}
- But the compiler will continue to compile. It will not, however, generate a
- unit file or a program (since an error occurred).
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Macros
- \section{Macros}
- \label{se:Macros}
- Macros are very much like symbols in their syntax, the difference 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 \var{-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 \var{\{\$define \}} preprocessor statement\footnote{In compiler
- versions older than 0.9.8, the assignment operator for a macros wasn't
- \var{:=}, but \var{=}}:
- \begin{verbatim}
- {$define ident:=expr}
- \end{verbatim}
- If the compiler encounters \var{ident} in the rest of the source file, it
- will be replaced immediately by \var{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:
- \begin{verbatim}
- {$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; }
- ...
- \end{verbatim}
- The previous example could go wrong :
- \begin{verbatim}
- {$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... }
- ...
- \end{verbatim}
- On my system, the last example results in a heap error, causing the compiler
- to exit with a run-time error 203.
- {\em 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 \seet{DefMacros}.
- \begin{FPCltable}{ll}{Predefined macros}{DefMacros} \hline
- Symbol & Contains \\ \hline
- \var{FPC\_VERSION} & The version number of the compiler. \\
- \var{FPC\_RELEASE} & The release number of the compiler. \\
- \var{FPC\_PATCH} & The patch number of the compiler. \\
- \hline
- \end{FPCltable}
- {\em Remark: } Don't forget that macros support isn't on by default. You
- need to compile with the \var{-Sm} command-line switch.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Using assembly language
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Using assembly language}
- \label{ch:AsmLang}
- \fpc supports inserting of assembler instructions in your code. The
- mechanism for this is the same as under Turbo Pascal. There are, however
- some substantial differences, as will be explained in the following.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Intel syntax
- \section{Intel syntax}
- \label{se:Intel}
- As of version 0.9.7, \fpc supports Intel syntax in it's \var{asm} blocks.
- The Intel syntax in your \var{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
- \fpc, but which exist in Turbo Pascal:
- \begin{itemize}
- \item The \var{TBYTE} qualifier is not supported.
- \item The \var{\&} identifier override is not supported.
- \item The \var{HIGH} operator is not supported.
- \item The \var{LOW} operator is not supported.
- \item The \var{OFFSET} and \var{SEG} operators are not supported.
- use \var{LEA} and the various \var{Lxx} instructions instead.
- \item Expressions with constant strings are not allowed.
- \item Access to record fields via parenthesis is not allowed
- \item Typecasts with normal pascal types are not allowed, only
- recognized assembler typecasts are allowed.\\ Example:
- \begin{verbatim}
- mov al, byte ptr MyWord -- allowed,
- mov al, byte(MyWord) -- allowed,
- mov al, shortint(MyWord) -- not allowed.
- \end{verbatim}
- \item Pascal type typecasts on constants are not allowed. \\
- Example:
- \begin{verbatim}
- const s= 10; const t = 32767;
- \end{verbatim}
- in Turbo Pascal:
- \begin{verbatim}
- mov al, byte(s) -- useless typecast.
- mov al, byte(t) -- syntax error!
- \end{verbatim}
- In this parser, either of those cases will give out a syntax error.
- \item Constant references expressions with constants only are not
- allowed (in all cases they do not work in protected mode,
- under linux i386). \\ Examples:
- \begin{verbatim}
- mov al,byte ptr ['c'] -- not allowed.
- mov al,byte ptr [100h] -- not allowed.
- \end{verbatim}
- (This is due to the limitation of Turbo Assembler).
- \item Brackets within brackets are not allowed
- \item Expressions with segment overrides fully in brackets are
- presently not supported, but they can easily be implemented
- in BuildReference if requested. \\ Example:
- \begin{verbatim}
- mov al,[ds:bx] -- not allowed
- \end{verbatim}
- use instead:
- \begin{verbatim}
- mov al,ds:[bx]
- \end{verbatim}
- \item Possible allowed indexing are as follows:
- \begin{itemize}
- \item \var{Sreg:[REG+REG*SCALING+/-disp]}
- \item \var{SReg:[REG+/-disp]}
- \item \var{SReg:[REG]}
- \item \var{SReg:[REG+REG+/-disp]}
- \item \var{SReg:[REG+REG*SCALING]}
- \end{itemize}
- Where \var{Sreg} is optional and specifies the segment override.
- {\em Notes:}
- \begin{enumerate}
- \item The order of terms is important contrary to Turbo Pascal.
- \item The Scaling value must be a value, and not an identifier
- to a symbol.\\ Examples:
- \begin{verbatim}
- const myscale = 1;
- ...
- mov al,byte ptr [esi+ebx*myscale] -- not allowed.
- \end{verbatim}
- use:
- \begin{verbatim}
- mov al, byte ptr [esi+ebx*1]
- \end{verbatim}
- \end{enumerate}
- \item Possible variable identifier syntax is as follows:
- (Id = Variable or typed constant identifier.)
- \begin{enumerate}
- \item \var{ID}
- \item \var{[ID]}
- \item \var{[ID+expr]}
- \item \var{ID[expr]}
- \end{enumerate}
- Possible fields are as follow:
- \begin{enumerate}
- \item \var{ID.subfield.subfield ...}
- \item \var{[ref].ID.subfield.subfield ...}
- \item \var{[ref].typename.subfield ...}
- \end{enumerate}
- \item Local Labels: Contrary to Turbo Pascal, local labels, must
- at least contain one character after the local symbol indicator.\\
- Example:
- \begin{verbatim}
- @: -- not allowed
- \end{verbatim}
- use instead, for example:
- \begin{verbatim}
- @1: -- allowed
- \end{verbatim}
- \item Contrary to Turbo Pascal local references cannot be used as references,
- only as displacements. \\ example:
- \begin{verbatim}
- lds si,@mylabel -- not allowed
- \end{verbatim}
- \item Contrary to Turbo Pascal, \var{SEGCS}, \var{SEGDS}, \var{SEGES} and
- \var{SEGSS} segment overrides are presently not supported.
- (This is a planned addition though).
- \item Contrary to Turbo Pascal where memory sizes specifiers can
- be practically anywhere, the \fpc Intel inline assembler requires
- memory size specifiers to be outside the brackets. \\
- example:
- \begin{verbatim}
- mov al,[byte ptr myvar] -- not allowed.
- \end{verbatim}
- use:
- \begin{verbatim}
- mov al,byte ptr [myvar] -- allowed.
- \end{verbatim}
- \item Base and Index registers must be 32-bit registers.
- (limitation of the GNU Assembler).
- \item \var{XLAT} is equivalent to \var{XLATB}.
- \item Only Single and Double FPU opcodes are supported.
- \item Floating point opcodes are currently not supported
- (except those which involve only floating point registers).
- \end{itemize}
- The Intel inline assembler supports the following macros :
- \begin{description}
- \item [@Result] represents the function result return value.
- \item [Self] represents the object method pointer in methods.
- \end{description}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % AT&T syntax
- \section{AT\&T Syntax}
- \label{se:AttSyntax}
- \fpc uses the \gnu \var{as} assembler to generate its object files. Since
- the \gnu assembler uses AT\&T assembly syntax, the code you write should
- use the same syntax. The differences between AT\&T and Intel syntax as used
- in Turbo Pascal are summarized in the following:
- \begin{itemize}
- \item 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, suffixed with a
- '\var{l}', '\var{w}' or '\var{b}' for, respectively, longint (32 bit),
- word (16 bit) and byte (8 bit) memory or register references. As an example,
- the Intel construct \mbox{'\var{mov al bl}} is equivalent to the AT\&T style '\var{movb
- \%bl,\%al}' instruction.
- \item AT\&T immediate operands are designated with '\$', while Intel syntax
- doesn't use a prefix for immediate operands. Thus the Intel construct
- '\var{mov ax, 2}' becomes '\var{movb \$2, \%al}' in AT\&T syntax.
- \item AT\&T register names are preceded by a '\var{\%}' sign.
- They are undelimited in Intel syntax.
- \item AT\&T indicates absolute jump/call operands with '\var{*}', Intel
- syntax doesn't delimit these addresses.
- \item The order of the source and destination operands are switched. AT\&T
- syntax uses '\var{Source, Dest}', while Intel syntax features '\var{Dest,
- Source}'. Thus the Intel construct '\var{add eax, 4}' transforms to
- '\var{addl \$4, \%eax}' in the AT\&T dialect.
- \item Immediate long jumps are prefixed with the '\var{l}' prefix. Thus the
- Intel '\var{call/jmp section:offset'} is transformed to '\var{lcall/ljmp
- \$section,\$offset}'. Similarly the far return is '\var{lret}', instead of the
- Intel '\var{ret far}'.
- \item Memory references are specified differently in AT\&T and Intel
- assembly. The Intel indirect memory reference
- \begin{quote}
- \var{Section:[Base + Index*Scale + Offs]}
- \end{quote}
- is written in AT\&T syntax as :
- \begin{quote}
- \var{Section:Offs(Base,Index,Scale)}
- \end{quote}
- Where \var{Base} and \var{Index} are optional 32-bit base and index
- registers, and \var{Scale} is used to multiply \var{Index}. It can take the
- values 1,2,4 and 8. The \var{Section} is used to specify an optional section
- register for the memory operand.
- \end{itemize}
- More information about the AT\&T syntax can be found in the \var{as} manual,
- although the following differences with normal AT\&T assembly must be taken
- into account :
- \begin{itemize}
- \item Only the following directives are presently supported:
- \begin{description}
- \item[.byte]
- \item[.word]
- \item[.long]
- \item[.ascii]
- \item[.asciz]
- \item[.globl]
- \end{description}
- \item The following directives are recognized but are not
- supported:
- \begin{description}
- \item[.align]
- \item[.lcomm]
- \end{description}
- Eventually they will be supported.
- \item Directives are case sensitive, other identifiers are not case sensitive.
- \item Contrary to GAS local labels/symbols {\em must} start with \var{.L}
- \item The nor operator \var{'!'} is not supported.
- \item String expressions in operands are not supported.
- \item Constant expressions which represent memory references are not
- allowed even though constant immediate value expressions are supported. \\
- examples:
- \begin{verbatim}
- const myid = 10;
- ...
- movl $myid,%eax -- allowed
- movl myid(%esi),%eax -- not allowed.
- \end{verbatim}
- \item When the \var{.globl} directive is found, the symbol following
- it is made public and is immediately emitted.
- Therefore label names with this name will be ignored.
- \item Only Single and Double FPU opcodes are supported.
- \end{itemize}
- The AT\&T inline assembler supports the following macros :
- \begin{description}
- \item [\_\_RESULT] represents the function result return value.
- \item [\_\_SELF] represents the object method pointer in methods.
- \item [\_\_OLDEBP] represents the old base pointer in recusrive routines.
- \end{description}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Calling mechanism
- \section{Calling mechanism}
- \label{se:Calling}
- Procedures and Functions are called with their parameters on the stack.
- Contrary to Turbo Pascal, {\em all} parameters are pushed on the stack, and
- they are pushed {\em right} to {\em 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 \fpc.
- Function results are returned in the first register, if they fit in the
- register. For more information on this, see \sees{Stack}
- The registers are {\em 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 (\var{\%ebp}) pointer equal to the stack pointer (\var{\%esp}).
- References to the pushed parameters and local variables are constructed
- using the base pointer.
- In practice this amounts to the following assembly code as the procedure or
- function header :
- \begin{verbatim}
- pushl %ebp
- movl %esp,%ebp
- \end{verbatim}
- When the procedure or function exits, it clears the stack by means of the
- \var{RET xx} call, where \var{xx} is the total size of the pushed parameters
- on the stack. Thus, in case parameters with a total size of \var{xx} have
- been passed to a function, the generated exit sequence looks as follows:
- \begin{verbatim}
- leave
- ret $xx
- \end{verbatim}
- 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. To avoid this problem, \fpc supports the \var{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.
- Technically, the C calling mechanism is implemented by generating the
- following exit sequence at the end of your function or procedure:
- \begin{verbatim}
- leave {Copies EBP to ESP, pops EBP from the stack.}
- ret
- \end{verbatim}
- Comparing this exit sequence with the previous one makes it clear why you
- cannot call this procedure from within Pascal: The arguments still are on
- the stack when the procedure exits.
- As of version 0.9.8, the \fpc compiler supports also the \var{cdecl} and
- \var{stdcall} modifiers, as found in Delphi. The \var{cdecl} modifier does
- the same as the \var{export} modifier, and \var{stdcall} does nothing, since
- \fpc pushes the paramaters from right to left by default.
- In addition to the Delphi \var{cdecl} construct, \fpc also supports the
- \var{popstack} directive; it is nearly the same a the \var{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 \seet{Calling}. 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.
- \begin{FPCltable}{llll}{Calling mechanisms in \fpc}{Calling}\hline
- Modifier & Pushing order & Stack cleaned by & Parameters in registers \\
- \hline
- (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 \\ \hline
- \end{FPCltable}
- More about this can be found in \seec{Linking} on linking.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Telling the compiler what registers have changed
- \section{Telling the compiler what registers have changed}
- \label{se:RegChanges}
- 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, \fpc 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:
- \begin{verbatim}
- asm
- ...
- end ['R1',...,'Rn'];
- \end{verbatim}
- Here \var{R1} to \var{Rn} are the names of the (extended) registers you
- modify in your assembly code. They can be one of \var{'EAX', 'EBX', 'ECX',
- 'EDX', 'EDI', 'ESI'} for the Intel processor.
- As an example :
- \begin{verbatim}
- asm
- movl BP,%eax
- movl 4(%eax),%eax
- movl %eax,__RESULT
- end ['EAX'];
- \end{verbatim}
- This example tells the compiler that the \var{EAX} register was modified.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Linking issues
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Linking issues}
- \label{ch:Linking}
- 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 C libraries, or to external
- object files that are generated using a C compiler (or even another pascal
- compiler). The \fpc compiler can generate calls to a C function,
- and can generate functions that can be called from C (exported functions).
- However, these exported functions cannot be called from
- inside Pascal anymore. More on these calling conventions can be found in
- \sees{Calling}.
- In general, there are 2 things you must do to use a function that resides in
- an external library or object file:
- \begin{enumerate}
- \item You must make a pascal declaration of the function or procedure you
- want to use.
- \item 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.
- \end{enumerate}
- The following sections attempt to explain how to do this.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Declaring an external function or procedure
- \section{Declaring an external function or procedure}
- \label{se:ExternalDeclaration}
- The first step in using external code blocks is declaring the function you
- want to use. \fpc supports Delphi syntax, i.e. you must use the
- \var{external} directive.
- There exist four variants of the external direcive :
- \begin{enumerate}
- \item A simple external declaration:
- \begin{verbatim}
- Procedure ProcName (Args : TPRocArgs); external;
- \end{verbatim}
- The \var{external} directive tells the compiler that the function resides in
- an external block of code. You can use this together with the \var{\{\$L \}}
- or \var{\{\$LinkLib \}} directives to link to a function or procedure in a
- library or external object file.
- \item You can give the \var{external} directive a library name as an
- argument:
- \begin{verbatim}
- Procedure ProcName (Args : TPRocArgs); external 'Name';
- \end{verbatim}
- This tells the compiler that the procedure resides in a library with name
- \var{'Name'}. This method is equivalent to the following:
- \begin{verbatim}
- Procedure ProcName (Args : TPRocArgs);external;
- {$LinkLib 'Name'}
- \end{verbatim}
- \item The \var{external} can also be used with two arguments:
- \begin{verbatim}
- Procedure ProcName (Args : TPRocArgs); external 'Name'
- name 'OtherProcName';
- \end{verbatim}
- This has the same meaning as the previous declaration, only the compiler
- will use the name \var{'OtherProcName'} when linking to the library. This
- can be used to give different names to procedures and functions in an
- external library.
- This method is equivalent to the following code:
- \begin{verbatim}
- Procedure OtherProcName (Args : TProcArgs); external;
- {$LinkLib 'Name'}
- Procedure ProcName (Args : TPRocArgs);
- begin
- OtherProcName (Args);
- end;
- \end{verbatim}
- \item Lastly, onder \windows and \ostwo, there is a fourth possibility
- to specify an external function: In \file{.DLL} files, functionas also have
- a unique number (their index). It is possible to refer to these fuctions
- using their index:
- \begin{verbatim}
- Procedure ProcName (Args : TPRocArgs); external 'Name' Index SomeIndex;
- \end{verbatim}
- This tells the compiler that the procedure \var{ProcName} resides in a
- dynamic link library, with index {SomeIndex}.
- \em{Remark:} Note that this is ONLY available under \windows and \ostwo.
- \end{enumerate}
- In earlier versions of the \fpc compiler, the following construct was
- also possible :
- \begin{verbatim}
- Procedure ProcName (Args : TPRocArgs); [ C ];
- \end{verbatim}
- This method is equivalent to the following statement:
- \begin{verbatim}
- Procedure ProcName (Args : TPRocArgs); cdecl; external;
- \end{verbatim}
- However, the \var{[ C ]} directive is no longer supoerted as of version
- 0.99.5 of \fpc, therefore you should use the
- \var{external} directive, with the \var{cdecl} directive, if needed.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Linking an object file in your program
- \section{Explicitly linking an object file in your program}
- \label{se:LinkIn}
- Having declared the external function 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 \var{\{\$L 'file.o'\}} directive.
- This will cause the linker to link in the object file \file{file.o}. On
- \linux systems, this filename is case sensitive. Under \dos, case isn't
- important. Note that \var{file.o} must be in the current directory if you
- don't specify a path. The linker will not search for \file{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 :
- \begin{verbatim}
- .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
- \end{verbatim}
- Then you can call this function with the following Pascal Program:
- \begin{verbatim}
- 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.
- \end{verbatim}
- With just two commands, this can be made into a program :
- \begin{verbatim}
- as -o fib.o fib.s
- pp fibo.pp
- \end{verbatim}
- This example supposes that you have your assembler routine in \file{fib.s},
- and your Pascal program in \file{fibo.pp}.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Linking your program to a library
- \section{Linking your program to a library}
- \label{se:LinkOut}
- To link your program to a library, the procedure depends on how you declared
- the external procedure. If you used thediffers a little from the
- procedure when you link in an object file. although the declaration step
- remains the same (see \ref{se:ExternalDeclaration} on how to do that).
- In case you used the follwing syntax to declare your procedure:
- \begin{verbatim}
- Procedure ProcName (Args : TPRocArgs); external 'Name';
- \end{verbatim}
- You don't need to take additional steps to link your file in, the compiler
- will do all that is needed for you.
- In case you used
- \begin{verbatim}
- Procedure ProcName (Args : TPRocArgs); external;
- \end{verbatim}
- You still need to explicity link to the library. This can be done in 2 ways:
- \begin{enumerate}
- \item You can tell the compiler in the source file what library to link to
- using the \var{\{\$LinkLib 'Name'\}} directive:
- \begin{verbatim}
- {$LinkLib 'gpm'}
- \end{verbatim}
- This will link to the \file{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.
- \item You can also tell the compiler on the command-line to link in a
- library: The \var{-k} option can be used for that. For example
- \begin{verbatim}
- ppc386 -k'-lgpm' myprog.pp
- \end{verbatim}
- Is equivalent to the above method, and tells the linker to link to the
- \file{gpm} library.
- \end{enumerate}
- As an example; consider the following program :
- \begin{verbatim}
- 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.
- \end{verbatim}
- This program can be compiled with :
- \begin{verbatim}
- pp prlen.pp
- \end{verbatim}
- Supposing, of course, that the program source resides in \file{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.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Making a shared library
- \section{Making a shared library}
- \label{se:SharedLib}
- \fpc supports making shared libraries in a straightforward and easy manner.
- If you want to make libraries for other \fpc 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.
-
- % Adapting your code
- \subsection{Adapting your code}
- 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 \var{Export}, as
- follows:
- \begin{verbatim}
- Procedure ExportedProcedure ; export;
- \end{verbatim}
- This tells the compiler that it shouldn't clear the stack upon exiting the
- procedure (see \sees{Calling}), thus enabling a C program to call your
- function. It also means that your Pascal program can't call this function,
- since it will be using the C calling mechanism.
- {\em Remark :} You can only declare a function as exported in the
- \var{Implementation} section of a unit. This function may {\em 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 \fpc compiler ''mangles'' the name you give your
- function. It makes the name all-uppercase, and adds the types of all
- parameters to it. For \fpc units, this doesn't matter, since the \file{.ppu}
- unit file contains all information to map your function declaration onto the
- mangled name in the object file. For a C programmer, who has no access to
- the \var{.ppu} file, this is not very convenient. That is why \fpc
- has the \var{Alias} modifier. The \var{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 :
- \begin{verbatim}
- Procedure AliasedProc; [ Alias : 'AliasName'];
- \end{verbatim}
- The procedure \var{AliasedProc} will also be known as \var{AliasName}. Take
- care, the name you specify is case sensitive (as C is).
- Of course, you want to combine these two features of \fpc, to export a
- function under a reasonable name; If you want to do that, you must first
- specify that the function is to be exported, and then only declare an alias:
- \begin{verbatim}
- Procedure ExportToCProc; Export; [Alias : 'procname'];
- \end{verbatim}
- After that, any C program will be able to use your procedure or function.
- {\em 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.
- % Compiling libraries
- \subsection {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 \var{static} or \var{shared} (\var{dynamical}) library.
- You can do this as follows, for a dynamical library:
- \begin{verbatim}
- ppc386 -Uld myunit
- \end{verbatim}
- On \linux this will leave you with a file \file{libmyunit.so}. On \windows
- and \ostwo, this will leave you with \file{myunit.dll}.
- If you want a static library, you can do
- \begin{verbatim}
- ppc386 -Uls myunit
- \end{verbatim}
- This will leave you with \file{libmyunit.a} and a file \file{myunit.ppl}.
- The \file{myunit.ppl} is the unit file needed by the \fpc compiler.
- The extension \file{.ppl} means that the file describes a unit that resides
- in a library.
- The resulting files are then libraries. To make static libraries, you need
- the \file{ranlib} or \var{ar} program on your system. It is standard on any
- \linux system, and is provided with the \file{GCC} compiler under \dos.
- {\em BEWARE:} This command doesn't include anything but the current unit in
- thelibrary. Other units are left out, so if you use code from other units,
- you must dpley them together with your library.
- % Moving units
- \subsection{Moving units into a library}
- You can put multiple units into a library with the \var{ppumove} command, as
- follows:
- \begin{verbatim}
- ppumove unit1 unit2 unit3 name
- \end{verbatim}
- This will move 3 units in 1 library (called \file{libname.so} on linux,
- \file{name.dll} on \windows) and it will create 3 files \file{unit1.ppl},
- \file{unit2.ppl} and \file{file3.ppl}, which are unit files, but which tell
- the compiler to look in library \var{name} when linking your executable.
- The \var{ppumove} program has options to create statical or dynammical
- libraries. It is provided with the compiler.
- % unit searching
- \subsection{Unit searching strategy}
- When you compile a program or unit, the compiler will by
- default always look for \file{.ppl} files. If it doesn't find one, it will
- look for a \file{.ppu} file. You can disable this behaviour by
- specifying the \var{-Cs} switch. This tells the compiler to make a static
- binary, and refrains it from looking for units which reside in a library.
- You can tell the compiler only to use dynamic libraries by specifying
- the \var{-Cd} switch; the compiler will then only look for \var{.ppl} files,
- and will give an error if it doesn't find one.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Objects
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Objects}
- \label{ch:Objects}
- In this short chapter we give some technical things about objects. For
- instructions on how to use and declare objects, see \refref.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Constructor and Destructor calls.
- \section{Constructor and Destructor calls}
- \label{se:ConsDest}
- When using objects that need virtual methods, the compiler uses two help
- procedures that are in the run-time library. They are called
- \var{Help\_Destructor} and \var{Help\_Constructor}, and they are written in
- assebly 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
- \var{Help\_Constructor}
- procedure before issuing the call to the real constuctor.
- 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 \var{Help\_Destructor} is inserted in every destructor declaration,
- just before the destructor's exit sequence.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % memory storage of Objects
- \section{Memory storage of objects}
- \label{se:ObjMemory}
- 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 \var{Constructor} method.
- If the object you defined has no virtual methods, then a \var{nil} is stored
- in the VMT pointer. This ensures that the size of objects is equal, whether
- they have virtual methods ore not.
- The memory allocated looks as in \seet{ObjMem}.
- \begin{FPCltable}{ll}{Object memory layout}{ObjMem} \hline
- Offset & What \\ \hline
- +0 & Pointer to VMT. \\
- +4 & Data. All fields in the order the've been declared. \\
- ... & \\
- \hline
- \end{FPCltable}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % The virtual method table.
- \section{The Virtual Method Table}
- \label{se:VMT}
- 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 anchestor's
- VMT (\var{Nil} if there is no anchestor), and then the pointers to all virtual
- methods. The VMT layout is illustrated in \seet{VMTMem}.
- The VMT is constructed by the compiler. Every instance of an object receives
- a pointer to its VMT.
- \begin{FPCltable}{ll}{Virtual Method Table memory layout}{VMTMem} \hline
- Offset & What \\ \hline
- +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, \var{Nil} if no ancestor available.\\
- +12 & Pointers to the virtual methods. \\
- ... & \\
- \hline
- \end{FPCltable}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Generated code
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Generated code}
- \label{ch:GenCode}
- The \fpc 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.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Units
- \section{Units}
- \label{se:Units}
- When you compile a unit, the \fpc compiler generates 2 files :
- \begin{enumerate}
- \item A unit description file (with extension \file{.ppu}).
- \item An assembly language file (with extension \file{.s}).
- \end{enumerate}
- 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 \file{.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 \var{-s} command-line
- option, the assembly file must be left on disk, so the assembler can be
- called later.
- The unit file contains all the information the compiler needs to use the
- unit:
- \begin{enumerate}
- \item Other used units, both in interface and implementation.
- \item Types and variables from the interface section of the unit.
- \item Function declarations from the interface section of the unit.
- \item Some debugging information, when compiled with debugging.
- \item A date and time stamp.
- \end{enumerate}
- Macros, symbols and compiler directives are {\em 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 \file{dumpppu}
- program, which shows the contents of the file.
- 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 \fpc compiler
- doesn't make one for you.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Programs
- \section{Programs}
- \label{se:Programs}
- When you compile a program, the compiler produces again 2 files :
- \begin{enumerate}
- \item An assembly language file containing the statements of your program,
- and memory allocations for all used variables.
- \item A linker response file. This file contains a list of object files the
- linker must link together.
- \end{enumerate}
- The link response file is, by default, removed from the disk. Only when you
- specify the \var{-s} command-line option or when linking fails, then the ile
- is left on the disk. It is named \file{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 different ways.
- It's name is \file{prt0.o}, and the
- source file resides in \file{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,
- set up the stack. Then it calls the main program.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % MMX Support
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{MMX support}
- \label{ch:MMXSupport}
- \section{What is it about ?}
- \label{se:WhatisMMXabout}
- \fpc 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 efficiently, the
- Pascal language needs to be extended. So Free Pascal allows
- to add for example two \var{array[0..3] of word},
- if MMX support is switched on. The operation is done
- by the \var{MMX} unit and allows people without assembler knowledge to take
- advantage of the MMX extensions.
- Here is an example:
- \begin{verbatim}
- uses
- MMX; { 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);
- var
- w3 : 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.
- \end{verbatim}
- \section{Saturation support}
- \label{se:SaturationSupport}
- 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 \var{MMX} unit. If you
- want to use them, you have simple turn the switch saturation on:
- \var{\$saturation+}
- Here is an example:
- \begin{verbatim}
- Program SaturationDemo;
- {
- example for saturation, scales data (for example audio)
- with 1.5 with rounding to negative infinity
- }
- var
- audio1 : 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.
- \end{verbatim}
- \section{Restrictions of MMX support}
- \label{se:MMXrestrictions}
- In the beginning of 1997 the MMX instructions were introduced in the
- Pentium processors, so multitasking systems wouldn't save the
- newly introduced MMX registers. 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 \var{EMMS} of the \var{MMX} unit.
- This routine restores the FPU registers.
- {\em 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 possible to perform each operation, some opertions
- give a type mismatch, see section \ref {se:SupportedMMX} 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 \var{MMX} unit must be always 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 \var{MMX} unit. The compiler can't
- check this, so you are responsible for this !
- \section{Supported MMX operations}
- \label{se:SupportedMMX}
- \section{Optimizing MMX support}
- \label{se:OptimizingMMX}
- Here are some helpful hints to get optimal performance:
- \begin{itemize}
- \item The \var{EMMS} call takes a lot of time, so try to seperate floating
- point and MMX operations.
- \item Use MMX only in low level routines because the compiler
- saves all used MMX registers when calling a subroutine.
- \item The NOT-operator isn't supported natively by MMX, so the
- compiler has to generate a workaround and this operation
- is inefficient.
- \item Simple assignements of floating point numbers don't access
- floating point registers, so you need no call to the \var{EMMS}
- procedure. Only when doing arithmetic, you need to call the \var{EMMS}
- procedure.
- \end{itemize}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Memory issues
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Memory issues}
- \label{ch:Memory}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % The 32-bit model
- \section{The 32-bit model.}
- \label{se:ThirtytwoBit}
- The \fpc Pascal compiler issues 32-bit code. This has several consequences:
- \begin{itemize}
- \item You need a i386 or higher 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.
- \item 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.
- \item The structures you define are unlimited in size. Arrays can be as long
- as you want. You can request memory blocks from any size.
- \end{itemize}
- 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:
- \begin{description}
- \item [Seg()] : Returned the segment of a memory address. Since segments have
- no more meaning, zero is returned in the \fpc run-time library implementation of
- \var{Seg}.
- \item [Ofs()] : Returned the offset of a memory address. Since segments have
- no more meaning, the complete address is returned in the \fpc implementation
- of this function. This has as a consequence that the return type is
- \var{Longint} instead of \var{Word}.
- \item [Cseg(), Dseg()] : Returned, respectively, the code and data segments
- of your program. This returns zero in the \fpc implementation of the
- system unit, since both code and data are in the same memory space.
- \item [Ptr] accepted a segment and offset 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 offset. If you want to retain the old
- functionality, you can recompile the run-time library with the
- \var{DoMapping} symbol defined. This will restore the Turbo Pascal
- behaviour.
- \item [memw and mem] these arrays gave access to the \dos memory. \fpc
- supports them, they are mapped into \dos memory space. You need the
- \var{GO32} unit for this.
- \end{description}
- You shouldn't use these functions, since they are very non-portable, they're
- specific to \dos and the ix86 processor. The \fpc 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.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % The stack
- \section{The stack}
- \label{se: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 :
- \begin{enumerate}
- \item If there are any parameters to be passed to the procedure, they are
- pushed from right to left on the stack.
- \item If a function is called that returns a variable of type \var{String},
- \var{Set}, \var{Record}, \var{Object} or \var{Array}, then an address to
- store the function result in, is pushed on the stack.
- \item If the called procedure or function is an object method, then the
- pointer to \var{self} is pushed on the stack.
- \item 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.
- \item The return address is pushed on the stack (by the \var{Call}
- instruction).
- \end{enumerate}
- The resulting stack frame upon entering looks as in \seet{StackFrame}.
- \begin{FPCltable}{llc}{Stack frame when calling a procedure}{StackFrame}
- \hline
- Offset & What is stored & Optional ? \\ \hline
- +x & parameters & Yes \\
- +12 & function result & Yes \\
- +8 & self & Yes \\
- +4 & Frame pointer of parent procedure & Yes \\
- +0 & Return address & No\\ \hline
- \end{FPCltable}
- The stack is cleared with the \var{ret} I386 instruction, meaning that the
- size of all pushed parameters is limited to 64K.
- The stack size is unlimited for all supported platforms. On the \var{GO32V2}
- platform, the minimum guaranteed stack is 128Kb, but this can be set with
- the \var{-Ctxxx} compiler switch.
- 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 effects are maybe not the same. On top of that, the \fpc
- run-time library has some extra possibilities, not available in Turbo
- Pascal. These extra possibilities are explained in the next subsections.
- % The heap grows
- \subsection{The heap grows}
- \fpc supports the \var{HeapEerror} 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, \var{HeapError} points to the \var{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.
- If the call to \var{GrowHeap} has failed, then a run-time error is generated,
- or nil is returned, depending on the \var{GrowHeap} result.
- If the call to \var{GrowHeap} was successful, then the needed memory will be
- allocated.
-
- % Using Blocks
- \subsection{Using Blocks}
- If you need to allocate a lot of small block for a small period, then you
- may want to recompile the run-time library with the \var{USEBLOCKS} symbol
- defined. If it is recompiled, then the heap management is done in a
- different way.
- The run-time library keeps a linked list of allocated blocks with size
- up to 256 bytes\footnote{The size can be set using the \var{max\_size}
- constant in the \file{heap.inc} source file.}. By default, it keeps 32 of
- these lists\footnote{The actual size is \var{max\_size div 8}.}.
- When a piece of memory in a block is deallocated, the heap manager doesn't
- really 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.
- % The splitheap
- \subsection{Using the split heap}
- {\em 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 alloated
- 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 you program is finished.
- In Turbo Pascal, you could foresee this, and mark the position of the heap
- (using the \var{Mark} function) when entering this particular part of your
- program, and release the occupied memory in one call with the \var{Release}
- call.
- For most purposes, this works very good. But sometimes, you may need to
- allocate something on the heap that you {\em 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 \var{mark}
- and \var{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 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 \var{TempHeap}
- symbol defined.
- This means that the following functions are available :
- \begin{verbatim}
- procedure Split_Heap;
- procedure Switch_To_Base_Heap;
- procedure Switch_To_Temp_Heap;
- procedure Switch_Heap;
- procedure ReleaseTempHeap;
- procedure GetempMem(var p : pointer;size : longint);
- \end{verbatim}
- \var{split\_heap} is used to split the heap. It cannot be called two times
- in a row, without a call to \var{releasetempheap}. \var{Releasetempheap}
- completely releases the memory used by the temporary heap.
- Switching temporarily back to the base heap can be done using the
- \var{switch\_to\_base\_heap} call, and returning to the temporary heap is done
- using the \var{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
- \var{switch\_heap} call, which will split the heap first if needed.
- A call to \var{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 :
- \begin{verbatim}
- 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' }
- ...
- \end{verbatim}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Accessing DOS memory under the GO32 extender
- \section{Accessing \dos memory under the Go32 extender}
- \label{se:AccessingDosMemory}
- Because \fpc 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 memory\footnote{Thanks to an explanation of
- Thomas schatzl (E-mail:\var{tom\_at\[email protected]}).}.
- In {\em Proteced Mode}, memory is accessed through {\em Selectors} and
- {\em Offsets}. You can think of Selectors as the protected mode
- equivalents of segments.
- In \fpc, a pointer is an offset into the \var{DS} selector, which points to
- the Data of your program.
- To access the (real mode) \dos memory, somehow you need a selector that
- points to the \dos memory.
- The \file{GO32} unit provides you with such a selector: The
- \var{DosMemSelector} variable, as it is conveniently called.
- You can also allocate memory in \dos's memory space, using the
- \var{global\_dos\_alloc} function of the \file{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:offset pair for it.
- \begin{verbatim}
- procedure dosalloc(var selector : word;
- var segment : word;
- size : longint);
- var result : longint;
- begin
- result := global_dos_alloc(size);
- selector := word(result);
- segment := word(result shr 16);
- end;
- \end{verbatim}
- (you need to free this memory using the \var{global\_dos\_free} function.)
- You can access any place in memory using a selector. You can get a selector
- using the \var{allocate\_ldt\_descriptor} function, and then let this selector
- point to the physical memory you want using the
- \var{set\_segment\_base\_address} function, and set its length using
- \var{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 \var{seg\_fillchar} function.
- After using the selector, you must free it again using the
- \var{free\_ldt\_selector} function.
- More information on all this can be found in the \unitsref, the chapter on
- the \file{GO32} unit.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Appendices
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \appendix
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Appendix A
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Anatomy of a unit file}
- \label{ch:AppA}
- A unit file consists of basically five parts:
- \begin{enumerate}
- \item A unit header.
- \item A file references part. This contains the references to used units
- and sources with name, checksum and time stamps.
- \item A definition part. Contains all type and procedure definitions.
- \item A Symbol part. Contains all symbol names and references to their
- definitions.
- \item A list of units that are in the implementation part.
- \end{enumerate}
- The header consists of a sequence of 20 bytes, together they give some
- information about the unit file, the compiler version that was used to
- generate the unit file, etc. The complete layout can be found in
- \seet{UnitHeader}. The header is generated by the compiler, and changes only
- when the compiler changes. The current and up-to-date header definition can
- be found in the \file{files.pas} source file of the compiler. Look in this
- file for the \var{unitheader} constant declaration.
- \begin{FPCltable}{ll}{Unit header structure.}{UnitHeader} \hline
- Byte & What is stored \\ \hline
- 0..3 & The letters 'PPU' in upper case. This acts as a check. \\
- 4..6 & The unit format as a 3 letter sequence : e.g. '0','1,'2' for format
- 12. \\
- 7,8 & The compiler version and release numbers as bytes. \\
- 9 & The target OS number. \\
- 10 & Unit flags.\\
- 11..14 & Checksum (as a longint). \\
- 15,16 & unused (equal to 255). \\
- 17..20 & Marks start of unit file. \\ \hline
- \end{FPCltable}
- After the header, in the second part, first the list of all source files for
- the unit is written. Each name is written as a direct copy of the string in
- memory, i.e. a length bytes, and then all characters of the string. This
- list includes any file that was included in the unit source with the
- \var{\{\$i file\}} directive. The list is terminated with a \var{\$ff} byte
- marker.
- After this, the list of units in the \var{uses} clause is written,
- together with their checksums. The file is written as a string, the checksum
- as a longint (i.e. four bytes). Again this list is terminated with a
- \var{\$ff} byte marker.
- After that, in the third part, the definitions of all types, variables,
- constants, procedures and functions are written to the unit file.
- They are written in the following manner: First a byte is written, which
- determines the kind of definition that follows. then follows, as a series of
- bytes, a type-dependent description of the definition. The exact byte order
- for each type can be found in \seet{DefDef}
- \begin{FPCltable}{lccl}{Description of definition fields}{DefDef} \\hline
- Type & Start byte & Size & Stored fields \\ \hline\hline
- Pointer & 3 & 4 & Reference to the type pointer points to. \\ \hline
- Base type & 2 & 9 &
- \begin{tabular}[t]{l}
- 1 byte to indicate base type. \\
- 4-byte start range \\
- 4-byte end range \\
- \end{tabular}\\ \hline
- Array type &5 & 16 &
- \begin{tabular}[t]{l}
- 4-byte reference to element type. \\
- 4-byte reference to range type.\\
- 4-byte start range (longint) \\
- 4-byte end range (longint)\\
- \end{tabular} \\ \hline
- Procedure & 6 & ? &
- \begin{tabular}[t]{l}
- 4-byte reference to the return type definition. \\
- 2 byte Word containing modifiers. \\
- 2 byte Word containing number of parameters. \\
- 5 bytes per parameter.\\
- 1 byte : used registers. \\
- String containing the mangled name. \\
- 8 bytes.
- \end{tabular}
- \\ \hline
- Procedural type & 21 & ? &
- \begin{tabular}[t]{l}
- 4-byte reference to the return type definition. \\
- 2 byte Word containing modifiers. \\
- 2 byte Word containing number of parameters. \\
- 5 bytes per parameter. \\
- \end{tabular}
- \\ \hline
- String & 9 & 1 & 1 byte containing the length of the string. \\
- Record & 15 & variable &
- \begin{tabular}[t]{l}
- Longint indicating record length \\
- list of fields, to be read as unit in itself. \\
- \var{\$ff} end marker.
- \end{tabular} \\ \hline
- Class & 18 & variable &
- \begin{tabular}[t]{l}
- Longint indicating data length \\
- String with mangled name of class.\\
- 4 byte reference to ancestor class.\\
- list of fields, to be read as unit in itself. \\
- \var{\$ff} end marker.
- \end{tabular} \\ \hline
- file & 16 & 1(+4) &
- \begin{tabular}[t]{l}
- 1 byte for type of file. \\
- 4-byte reference to type of typed file.
- \end{tabular}\\ \hline
- Enumeration & 19 & 4 & Biggest element. \\ \hline
- set & 20 & 5 &
- \begin{tabular}[t]{l}
- 4-byte reference to set element type. \\
- 1 byte flag.
- \end{tabular} \\ \hline \hline
- \end{FPCltable}
- This list of definitions is again terminated with a \var{\$ff} byte marker.
- After that, a list of symbols is given, together with a reference to a
- definition. This represents the names of the declarations, and the
- definition they refer to.
- A reference consists of 2 words : the first word indicates the unit number
- (as it appears in the uses clause), and the second word is the number of the
- definition in that unit. A \var{nil} reference is stored as \var{\$ffffffff}.
- After this follows again a \var{\$ff} byte terminated list of filenames: The
- names of the units in the \var{uses} clause of the implementation section.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Appendix B
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %\chapter{Compiler and RTL source tree structure}
- %\label{ch:AppB}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Appendix C
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Compiler limits}
- \label{ch:AppC}
- 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:
- \begin{enumerate}
- \item String constants are limited to 128 characters. All other characters
- are simply dropped from the definition.
- \item The length of generated unit files is limited to 65K for the
- real-mode compiler, and to 1Mb for the 32-bit compiler. This limit can be
- changed by changing the \var{bytearray1} type in \file{cobjects.pas}
- \item Procedure or Function definitions can be nested to a level of 32.
- \item Maximally 255 units can be used in a program when using the real-mode
- compiler. When using the 32-bit compiler, the limit is set to 1024. You can
- change this by redefining the \var{maxunits} constant in the
- \file{files.pas} compiler source file.
- \item Procedures or functions accept parameters with a total size up to
- \var{\$ffff} bytes. This limit is due to the \var{RET} instruction of the I386
- processor. If the calls were made using the C convention this limit would
- disappear.
- \end{enumerate}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Appendix D
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Optimizing techniques used in the compiler.}
- Here follows a listing of the opimizing techniques used in the compiler:
- \begin{enumerate}
- \item When optimizing for a specific Processor (\var{-O3, -O4, -O5 -O6},
- the following is done:
- \begin{itemize}
- \item In \var{case} statements, a check is done whether a jump table
- or a sequence of conditional jumps should be used for optimal performance.
- \item Determines a number of strategies when doing peephole optimization:
- \var{movzbl (\%ebp), \%eax} on PentiumPro and PII systems will be changed
- into \var{xorl \%eax,\%eax; movb (\%ebp),\%al } for lesser systems.
- \end{itemize}
- Cyrix \var{6x86} processor owners should optimize with \var{-O4} instead of
- \var{-O5}, because \var{-O5} leads to larger code, and thus to smaller
- speed, according to the Cyrix developers FAQ.
- \item When optimizing for speed (\var{-OG}) or size (\var{-Og}), a choice is
- made between using shorter instructions (for size) such as \var{enter \$4},
- or longer instructions \var{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.
- \item Simple optimization (\var{-Oa}) makes sure the peephole optimizer is
- used, as well as the reloading optimizer.
- \item Maximum optimization (\var{-Ox}) avoids creation of stack frames if
- they aren't required, and unnecessary loading of registers is avoided as
- much as possible. (buggy at the moment (version 0.99.0).
- \item Uncertain optimizations (\var{-Oz}): With this switch, the reloading
- optimizer (enabled with \var{-Oa}) can be forced into making uncertain
- optimizations.
- You can enable uncertain optimizations only in certain cases,
- otherwise you will produce a bug; the following technical description
- tells you when to use them:
- \begin{quote}
- % Jonas's own words..
- \em
- If uncertain optimizations are enabled, the reloading optimizer assumes
- that
- \begin{itemize}
- \item If something is written to a local/global register or a
- procedure/function parameter, this value doesn't overwrite the value to
- which a pointer points.
- \item If something is written to memory pointed to by a pointer variable,
- this value doesn't overwrite the value of a local/global variable or a
- procedure/function parameter.
- \end{itemize}
- % end of quote
- \end{quote}
- The practical upshot of this is that you cannot use the uncertain
- optimizations if you access any local or global variables through pointers. In
- theory, this includes \var{Var} parameters, but it is all right
- if you don't both read the variable once through its \var{Var} reference
- and then read it using it's name.
- The following example will produce bad code when you switch on
- uncertain optimizations:
- \begin{verbatim}
- 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.
- \end{verbatim}
- The reason it produces bad code is because you access the global variable
- \var{Temp} both through its name \var{Temp} and through a pointer, in this
- case using the \var{Bar} variable parameter, which is nothing but a pointer
- to \var{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 {\em only} access them through this pointer\footnote{
- You can use multiple pointers to point to the same variable as well, that
- doesn't matter.}.
- For example:
- \begin{verbatim}
- 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.
- \end{verbatim}
- Will produce correct code, because the global variable \var{MyRecArrayPtr}
- is not accessed directly, but through a pointer (\var{MyRecPtr} in this
- case).
- In conclusion, one could say that you can use uncertain optimizations {\em
- only} when you know what you're doing.
- \end{enumerate}
- \end{document}
|