Digital Design
Digital Design
TIGCC Documentation
TIGCC v0.95 (Library v2.6)
Contents
How to...
Warning: This documentation, although quite complete, is not really a full C tutorial: it is assumed that you already know basic programing in C on any
standard computer (PC, Mac, etc.).
TIGCC is a C/ASM cross compiler for the TI-89, TI-92 Plus, and V200. The current release is v0.95. It is a complex project created by the following international
team:
Release Information
About TIGCC
Restrictions
Reporting Bugs
Documenting Unknown Functions
Credits
History
Disclaimer
Release Information
TIGCC v0.95 based on the GNU Compiler Collection v3.3.1 and GNU Binutils v2.14 compiled under MinGW32 by Jean Canazzi, Sebastian Reichelt, and
Kevin Kofler
A68k v2.71.F3i by Charlie Gibbs, David Ellsworth, Kevin Kofler, Julien Muchembled, and Paul Froissart
Amiga Port for binutils by Geek Gadgets
ld-tigcc v1.02 by Sebastian Reichelt and Kevin Kofler
TIGCC Library v2.6 by Zeljko Juric
TIGCC IDE v2.92 and Windows Command Line Executable by Sebastian Reichelt
Parameter passing by register Copyright (C) 1998-2003 Fred Fish from Geek Gadgets; converted to GCC 3.0 by Kevin Kofler
Parts from the TIGCC Tools Suite by the TI-Chess Team (i.e. Thomas Nussbaumer) as well as his grayscale support have been used.
TIGCC Tools Suite Copyright (C) 2000-2003 Thomas Nussbaumer
A slightly more advanced patch was originally made by François Revol (mmu_man).
About TIGCC
TIGCC is our attempt to make it possible to program in C for the TI-89 and TI-92 Plus. To do this, we originally recompiled a version of GCC-M68k (which was
found here) to make it work with the C calling convention used by TI's compiler. Then we wrote a linker to make it produce .89z or .9xz files. And since we
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 2 of 173
also wanted to allow the use of assembly, we programmed it so that you can use the .asm files and compile them with the A68k assembler. Finally we wrote
tigcc, a program which will automatically call the necessary programs to compile everything you specify in the command line. This was the first public release
of TIGCC.
At that time, Zeljko Juric (i.e. me, because I am writing this documentation) was quite new in TI community (he bought his TI-89 in July 1999). Although he
was a good ASM programmer (in Z80 and 80x86 assembler), he found ASM programming on TI calculators a bit unconfortable, so he started searching for a
high-level language compiler for TI-89 (TI-Basic was too slow and somewhat limited). Some compilers were written, but they were quite primitive (one of them
was usable anyway: Fargo Pascal, which is transformed later in Ultra Pascal). Then he found a first release of TIGCC...
Some testing proved that it produced quite usable code. But there was a complete lack of library functions. There was just one header file named romcalls.h
which was partially usable only for "Doors" programming. Implemented romcalls were possible to use only under the "DoorsOS" kernel. As Zeljko was not a
follower nor a lover of the "kernel" concept, he started to think how to use romcalls without any kernels. After a bit of researching, he suceeded to construct a
rom-calling macro which worked independently of any kernel, by calling TIOS functions directly.
In the meantime, Xavier stopped the development of the still buggy linker for a while; that was why Niklas Brunlid corrected some of the bugs because he
needed TIGCC for his project (Prosit). During this period, Zeljko started to research the (almost completely undocumented) TIOS entry points. He discovered
that TIOS itself contains many very useful routines which were usually implemented in various external libraries for kernel-based programming. So the natural
decision was to make a library of routines, based exclusively on TIOS entries, which would be usable for both kernel-less and kernel-based programming (and
to document everything what was found, of course). This was how the TIGCC Library was founded in the beginning of 2000.
After the release of the TIGCC Library, Xavier started to continue developing TIGCC, so integrating the library as an integral part of TIGCC was the next step.
This way Zeljko became a member of TIGCC team. He continued to research the dark, deep, and (previously) unknown parts of the operating system to be able
to upgrade the library with new routines. So, at the end of March, version 1.5 of the library was released, with a lot of new functions, and also with floating
point support (although it had a few bugs at first).
For a long time, TIGCC was just a command line compiler. Sebastian Reichelt started developing a window-based Integrated Environment for TIGCC in April.
First versions of it were quite simple, but later some more advanced options were added to it. In the meantime, Zeljko continued researching and developing.
Many people pointed out that the lack of "standard" ANSI C library routines like "fopen" etc. was a big disadvantage of TIGCC, so Zeljko decided to implement
them in the TIGCC library. The main problem was the impossibility of creating external archives of library routines (the linker did not support them). Then he
discovered a black art of cast constructors which allowed implementing these routines in a quite efficient way, using extremely dirty hacks. The main goal was
that the routines which were not used in the program would not be part of the final executable in any way, but if the routines were used, they were supposed to
be included only once. This behaviour was implemented successfully, so version 2.0 was released. This release included about 300 new functions compared to
the previous release!
Finally, Xavier, Sebastian and Zeljko decided to put everything together and stop distributing various part of TIGCC (compiler, linker, library and environment)
independently. Instead, starting from release 0.7, TIGCC contained everything packed in one file. The included library was now release 2.2 (which had stable
floating point support, established in release 2.1).
The most important recent change was a complete recompilation of GCC using the sources from the official Cygwin site. This recompilation made it possible to
work on the compiler again, which was impossible before because the sources were lost. Native floating point support was implemented by Sebastian in
November and December, while Zeljko created the appropriate library functions for this.
When Sebastian Reichelt and Kevin Kofler found and patched a working AmigaOS to COFF converter at the Geek Gadgets site, the linker was not needed as a
true linker any more, but rather as a converter from the COFF to the TI executable format. Therefore Julien Muchembled contributed a converter of his own,
which was much better than the previous link.
Although the version you are using now has evolved from a lot of different little updates, it is more or less a complete, working product. Changes are still being
made, though, and there is still a long way ahead for TIGCC.
Restrictions
Reporting Bugs
There may still be some bugs in the linker, in tigcc, and in the IDE. If you encounter a bug, please use the bug report form on the Official TIGCC Site, or send
all the information that is needed to the appropriate team member.
The TIGCC Library still contains a lot of unknown functions. They are defined in unknown.h. For some of them, prototypes are already available; some are even
partially documented. Others are completely unknown.
If you have information about one of these functions (also from TI's documentation, but you may not simply copy the information there for copyright reasons),
please take the time to document it. The way to do this is very simple, and you will be doing everyone using this library a big favor.
At first, you need the TIGCC source code, available from the TIGCC Website. Set up the documentation system according to the Readme file, and check whether
you can update at least the header files by running UpdateInclude.exe.
To document a file, or to change the file's prototype, you simply need to edit the appropriate .hsf file in the unknown.h subfolder of the help system. If you
have enough documentation to move it to another header file, simply move the .hsf file to the appropriate folder, and update all links from and to the file. (For
links from other files to this one, you will probably want to use a string replacement program to make the conversion automatically.) Then run
UpdateInclude.exe on both the new folder and on unknown.h (if it used to be in unknown.h). Now you will be able to view your documentation in a web
browser, and test the function with its new prototype.
When you are finished, please simply send the resulting .hsf file to [email protected]. We prefer compressed files because mail systems sometimes mess up
attached text files, but it doesn't really matter a lot.
Credits
These are the people we would like to thank for their contributions to TIGCC:
Thomas Nussbaumer (website), for his grayscale 'port' from Universal OS, and for the packing tools in the TIGCC Tools Suite (available on tict.ticalc.org)
François Revol, for his help on GCC-related issues
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 3 of 173
John David Ratliff (website), for his tutorials and for the CGI script for the bug report form
Peter J. Rowe, for correcting grammar and spelling mistakes in a large part of the documentation
Gereon Kindler, for the title and wizard images and the new icons in the IDE
Jocelyn Berrendonner, for his immense work on menus.h (already integrated) and dialogs.h (not integrated yet)
Romain Liévin (website), for the Linux port, the document about the internals of TIGCC, and work on the documentation
Lionel Debroux (website), for documenting AMS 2.xx functions from unknown.h
Samuel Stearley, for most of the home screen functions defined in homescr.h
Olivier Armand, for an improved internal Line 1111 emulator
Greg Dietsche, for a lot of updates to stdio.h
Joel Thompson, for extracting the examples from the documentation, and for some other updates (e.g. to gdraw.h and vat.h)
Daniel De Graaf, for updates to gdraw.h and estack.h
Ephyx, for the IDE code completion patches
History
Note: Click here for the history of the library, or here for the history of the IDE.
October 24, 2004: TIGCC v0.95, ld-tigcc v1.06, Library v2.6, IDE v2.92
Added: An entirely new linker, as a basis for all other improvements (see Advanced Options of TIGCC).
Added: Support for dynamic BSS sections in nostub mode.
Added: Linker-side code optimization.
Added: Support for data variables.
Added: Support for contructors and destructors.
Added: Experimental optional Fargo II support.
Updated: Patched GCC 3.3.1 with the TIGCC patch.
Updated: Updated PPG launcher created by the TI-Chess Team.
Added: Basic TI-89 Titanium support.
January 24, 2003: TIGCC v0.94 SP4, Obj2TI v1.01e, Library v2.5 SP4, IDE v2.91
January 13, 2003: TIGCC v0.94 SP3, Obj2TI v1.01e, Library v2.5 SP3, IDE v2.91
January 12, 2003: TIGCC v0.94 SP2, Obj2TI v1.01e, Library v2.5 SP2, IDE v2.91
December 30, 2002: TIGCC v0.94 SP1, Obj2TI v1.01e, Library v2.5 SP1, IDE v2.91
December 21, 2002: TIGCC v0.94, Obj2TI v1.01e, Library v2.5, IDE v2.91
Updated: Patched GCC 3.2.1 with the TIGCC patch, with a lot of modifications.
Updated: Greatly changed the internal structure of the library.
Added: Applied a patch for argument passing through registers.
Added: Implemented F-Line ROM Calls.
Added: Implemented support for PreOS libraries in obj2ti.
Bugfix: Repaired the '-freg-relative-reg' option.
Updated: Created an option to ignore system folders in the setup program.
Added: Finally wrote a program to update the version numbers in all places.
Updated: Enhanced the help file tools to generate the header files as well.
Added: Added tools to edit the help system files.
Added: Implemented HTML checking for help system files.
Added: Added a switch to tigcc to create archives.
Updated: Made tigcc look for archives in the 'Lib' subfolder of the installation.
Updated: Repaired some bugs to support debugging switches like '-ggdb'.
Updated: Recompiled all programs under MinGW32, thereby removing the need to use Cygwin.
Updated: Compressed setup program using UPX.
Added: Added "See Also" links to the help system.
Added: Extracted all examples from the documentation, with a lot of help from Joel Thompson.
Added: Added support for nostub libraries.
Added: Added missing long long operator support.
February 3, 2002: TIGCC v0.93, Obj2TI v1.01, Library v2.41, IDE v2.9
November 25, 2001: TIGCC v0.92 SP2, Obj2TI v1.01, Library v2.4 SP1, IDE v2.8 SP4
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 4 of 173
November 9, 2001: TIGCC v0.92 SP1, Obj2TI v1.01, Library v2.4 SP1, IDE v2.8 SP3
Bugfix: Fixed the problem in obj2ti with uninitialized global variables in kernel mode.
Bugfix: Fixed the A68k integration problem (in objcopy) which prevented RAM calls from being used in 16-bit addressing mode.
Bugfix: Fixed the IDE bug which made closing large files really slow.
Added: In the IDE, it is now possible to switch between files quickly using Ctrl+Tab.
Updated: The program decompressor is stored as an object file now, instead of an assembly file; this removes the need to run the assembler for
compression.
Updated: Greatly updated the setup program to prevent legal problems.
September 29, 2001: TIGCC v0.92, Obj2TI v1.0, Library v2.4 SP1, IDE v2.8 SP2
Updated: Applied the TIGCC patch to GCC 3.0, which introduces some optimizations and more warnings.
Updated: Replaced Xavier's linker with new obj2ti by Julien Muchembled.
Added: Added an AmigaOS to COFF converter for A68k programs. This allows for seamless A68k integration in TIGCC.
Updated: Included new 32-bit version of A68k by Kevin Kofler.
Updated: Implemented floating point constant folding. The floating point system can now be used the same way as on any other machine.
Added: The '-Wl,...' and '-Wa,...' options are now available in the command line compiler. This means that you can pass options to the GNU assembler
and GNU linker.
May 1, 2001: TIGCC v0.91 SP1, Link v1.2, Library v2.4 SP1, IDE v2.8 SP1
March 24, 2001: TIGCC v0.91, Link v1.2, Library v2.4, IDE v2.8
Added: Support for multiple files is now stable since the GNU linker is used.
Added: Archives (extension .a) are now supported. A file tigcc.a has been created, which is included automatically in all projects.
Added: Important debug information is now included in the .s file(s) if a program is compiled with the '-g' switch or with the corresponding option in the
IDE.
Added: Support for binary values (0b...) has been implemented, but its use is strongly deprecated for portability reasons.
Updated: Various updates in the IDE have been made.
December 18, 2000: TIGCC v0.9, Link v1.2, Library v2.3, IDE v2.71
October 11, 2000: TIGCC v0.8, Link v1.2, Library v2.22, IDE v2.7
June 26, 2000: TIGCC v0.7, Link v1.2, Library v2.0, IDE v2.6
Bugfix: sometimes some weird characters were appended to the file name and it wasn't compiled.
Updated: TIGCCLIB is now version 1.5.
Bugfix: C symbols that where exported out-of-order by GCC (i.e. library@0000, library@0002, library@0001...) are now inserted properly in
the .89z/.9xz file. This will make it possibe to write libraries in C the way it should be done.
Bugfix: The _comment symbol is now properly recognized in both C and assembly programs. Added: Both tigcc and link now have the '-q' option for
quiet assembling or compilation. Does not affect warnings and errors.
The source of link and tigcc is included in the distribution.
Initial release.
Disclaimer
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 5 of 173
Original files Copyright (C) 1999-2004 Xavier Vassor, Niklas Brunlid, and Jean Canazzi
ld-tigcc Copyright (C) 2002-2004 Sebastian Reichelt and Kevin Kofler
Library Copyright (C) 2000-2004 Zeljko Juric
IDE Copyright (C) 2000-2004 Sebastian Reichelt
Some parts of the TIGCC package are parts of the GNU C compiler package. Like the rest of TIGCC, these parts are free software; you can redistribute them
and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program 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.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA.
C Language Keywords
auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
In addition to these standard keywords, TIGCC recognizes some extended keywords which do not exist in ANSI C, like asm, typeof, inline, etc., which are
described in details in the section GNU C language extensions. This section also describes extensions to standard keywords, not only new ones.
Note: If square brackets '[...]' are used in syntax descriptions, they mean optional arguments (as usual in syntax-describing languages), not square brackets
as literals.
auto Keyword
Keyword Index
[auto] data-definition;
As the local lifetime is the default for local variables, auto keyword is extremely rarely used.
Note: GNU C extends auto keyword to allow forward declaration of nested functions.
break Keyword
Keyword Index
The break statement causes control to pass to the statement following the innermost enclosing while, do, for, or switch statement. The syntax is simply
break;
Keyword Index
Branches control.
switch causes control to branch to one of a list of possible statements in the block of statements. The syntax is
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 6 of 173
The statement statement is typically a compound statement (i.e. a block of statements enclosed in braces). The branched-to statement is determined by
evaluating expression, which must return an integral type. The list of possible branch points within statement is determined by preceding substatements with
case constant-expression :
Once a value is computed for expression, the list of possible constant-expression values determined from all case statements is searched for a match. If a
match is found, execution continues after the matching case statement and continues until a break statement is encountered or the end of statement is
reached. If a match is not found and this statement prefix is found within statement,
default :
execution continues at this point. Otherwise, statement is skipped entirely. For example,
switch (operand)
{
case MULTIPLY:
x *= y; break;
case DIVIDE:
x /= y; break;
case ADD:
x += y; break;
case SUBTRACT:
x -= y; break;
case INCREMENT2:
x++;
case INCREMENT1:
x++; break;
case EXPONENT:
case ROOT:
case MOD:
printf ("Not implemented!\n");
break;
default:
printf("Bug!\n");
exit(1);
}
Keyword Index
Variables of type int are one machine-type word in length. They can be signed (default) or unsigned, which means that in this configuration of the compiler they
have by default a range of -32768 to 32767 and 0 to 65535 respectively, but this default may be changed if the compiler option '-mnoshort' is given. In this
case, the range of type int is -2147483648 to 2147483647 for signed case, or 0 to 4294967295 for unsigned case. See also short and long type modifiers.
Variables of type char are 1 byte in length. They can be signed (this is the default, unless you use the compiler option '-funsigned-char') or unsigned, which
means they have a range of -128 to 127 and 0 to 255, respectively.
All data types may be used for defining variables, specifying return types of functions, and specifying types of function arguments. For example,
All data type keywords may be used in combination with asterisks, brackets and parentheses, for making complex data types, like pointer types, array types,
function types, or combinations of them, which in the C language may have an arbitrary level of complexity (see asterisk for more info).
const Keyword
Keyword Index
In this case, the const modifier allows you to assign an initial value to a variable that cannot later be changed by the program. For example,
Any assignments to 'my_age' will result in a compiler error. However, such declaration is quite different than using
#define my_age 32
In the first case, the compiler allocates a memory for 'my_age' and stores the initial value 32 there, but it will not allow any later assignment to this variable.
But, in the second case, all occurences of 'my_age' are simply replaced with 32 by the preprocessor, and no memory will be allocated for it.
Warning: a const variable can be indirectly modified by a pointer, as in the following example:
*(int*)&my_age = 35;
When the const modifier is used with a pointer parameter in a function's parameter list, it uses the following syntax:
Then, the function cannot modify the variable that the pointer points to. For example,
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 7 of 173
Here the printf function is prevented from modifying the format string.
continue Keyword
Keyword Index
continue causes control to pass to the end of the innermost enclosing while, do, or for statement, at which point the loop continuation condition is re-
evaluated. The syntax is simply
continue;
For example,
This example changes each element in the array with its reciprocal, but skips elements which are equal to zero.
do Keyword
Keyword Index
Do-while loop.
Keyword do is usually used together with while to make another form of repeating statement. Such form of the loop uses the following syntax:
statement, which is usually a compound statement, is executed repeatedly as long as the value of expression remains non-zero. The test takes place after each
execution of the statement. For example,
i = 1; n = 1;
do
{
n *= i;
i++;
} while (i <= factorial);
Keyword Index
The keyword float usually represents a single precision floating point data type, and double represents a double precision floating point data type. In TIGCC,
both float and double (and even long double) are the same. The TI-89 and TI-92 Plus use a non-IEEE floating point format called SMAP II BCD for floating
point values.
These values have a range from 1e-999 to 9.999999999999999e999 in magnitude, with a precision of exactly 16 significant digits. Principally, the exponent
range may be as high as 16383, but a lot of math routines do not accept exponents greater than 999.
Keyword Index
Conditional statement.
Keyword if is used for conditional execution. The basic form of if uses the following syntax:
if (expression)
statement1
Alternatively, if may be used together with else, using the following syntax:
if (expression)
statement1
else
statement2
If expression is nonzero when evaluated, then statement1 is executed. In the second case, statement2 is executed if the expression is 0.
An optional else can follow an if statement, but no statements can come between an if statement and an else. Of course, both statement1 and statement2
may be compound statements (i.e. a sequence of statements enclosed in braces). Here will be given some legal examples:
if (x < y) z = x;
else z = y;
if (x < y)
{
printf ("x is smaller");
return x;
}
else
{
printf ("x is greater")
return y;
}
The #if and #else preprocessor statements look similar to the if and else statements, but have very different effects. They control which source file lines are
compiled and which are ignored.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 8 of 173
enum Keyword
Keyword Index
The set can optionally be given a type tag name with tag. name is the name of a constant that can optionally be assigned the (constant) value of value, etc. For
example,
If value is missing, then a value is assumed to be the value of the previous constant in the list + 1. If this is the first constant in the list, the default value is 0.
If you give a type tag name, then you can declare variables of enumerated type using
For example,
enum Numbers x, y, z;
declares three variables x, y and z, all of type Numbers (they are, in fact, integer variables). More precise, 'enum tag' becomes a new type which is equal in
rights with any built-in type.
extern Keyword
Keyword Index
Keyword extern indicates that the actual storage and initial value of a variable, or body of a function, is defined elsewhere, usually in a separate source code
module. So, it may be applied to data definitions and function prototypes:
extern data-definition;
extern function-prototype;
For example,
for Keyword
Keyword Index
For loop.
For-loop is yet another kind of loop. It uses for keyword, with the following syntax:
statement is executed repeatedly until the value of expr2 is 0. Before the first iteration, expr1 is evaluated. This is usually used to initialize variables for the
loop. After each iteration of the loop, expr3 is evaluated. This is usually used to increment a loop counter. In fact, the for-loop is absolutely equivalent to the
following sequence of statements:
expr1;
while (expr2)
{
statement;
expr3;
}
That's why expr1 and expr3 must contain side effects, else they are useless. For example,
All the expressions are optional. If expr2 is left out, it is assumed to be 1. statement may be a compound statement as well.
goto Keyword
Keyword Index
goto may be used for transfering control from one place to another. The syntax is:
goto identifier;
Control is unconditionally transferred to the location of a local label specified by identifier. For example,
Again:
...
goto Again;
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 9 of 173
Jumping out of scope (for example out of the body of the for loop) is legal, but jumping into a scope (for example from one function to another) is not allowed.
Note: The GNU C extends the usage of goto keyword to allow computed goto. Also, it supports local labels, useful in macro definitions.
Keyword Index
Type modifiers.
A type modifier alters the meaning of the base type to yield a new type. Each of these type modifiers can be applied to the base type int. The modifiers signed
and unsigned can be applied to the base type char. In addition, long can be applied to double.
When the base type is omitted from a declaration, int is assumed. For example,
In this implementation of the compiler, the valid range of valid data types is as listed in the following table:
Note: GNU C extends the long keyword to allow double-long integers (64-bit integers in this implementation), so they have range from -
9223372036854775808 to 9223372036854775807 if signed, or from 0 to 18446744073709551615 if unsigned.
register Keyword
Keyword Index
Tells the compiler to store the variable being declared in a CPU register.
register data-definition;
The register type modifier tells the compiler to store the variable being declared in a CPU register (if possible), to optimize access. For example,
register int i;
Note that TIGCC will automatically store often used variables in CPU registers when the optimization is turned on, but the keyword register will force storing in
registers even if the optimization is turned off. However, the request for storing data in registers may be denied, if the compiler concludes that there is not
enough free registers for use at this place.
Note: The GNU C extends the usage of register keyword to allow explicitely choosing of used registers.
return Keyword
Keyword Index
return exits immediately from the currently executing function to the calling routine, optionally returning a value. The syntax is:
return [expression];
For example,
sizeof Keyword
Keyword Index
Keyword sizeof is, in fact, an operator. It returns the size, in bytes, of the given expression or type (as type size_t). Its argument may be an expression of a
type name:
sizeof expression
sizeof (type)
For example,
Note that type may be an anonymous type (see asterisk for more info about anonymous types).
static Keyword
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 10 of 173
Keyword Index
static data-definition;
static function-definition;
For example,
static tells that a function or data element is only known within the scope of the current compile. In addition, if you use the static keyword with a variable
that is local to a function, it allows the last value of the variable to be preserved between successive calls to that function.
Note that the initialization of automatic and static variables is quite different. Automatic variables (local variables are automatic by default, except you
explicitely use static keyword) are initialized during the run-time, so the initialization will be executed whenever it is encountered in the program. Static (and
global) variables are initialized during the compile-time, so the initial values will simply be embeded in the executable file itself. If you change them, they will
retain changed in the file. By default, the C language proposes that all uninitialized static variables are initialized to zero, but due to some limitations in TIGCC
linker, you need to initialize explicitely all static and global variables if you compile the program in "nostub" mode.
The fact that global and static variables are initialized in compile-time and kept in the executable file itself has one serious consequence, which is not present on
"standard" computers like PC, Mac, etc. Namely, these computers always reload the executable on each start from an external memory device (disk), but this is
not the case on TI. So, if you have the following global (or static) variable
int a = 10;
and if you change its value somewhere in the program to 20 (for example), its initial value will be 20 (not 10) on the next program start! Note that this is true
only for global and static variables. To force reinitializing, you must put explicitely something like
a = 10;
Note, however, that if the program is archived, the initial values will be restored each time you run the program, because archived programs are reloaded from
the archive memory to the RAM on each start, similarly like the programs are reloaded from disks on "standard" computers each time when you start them.
struct Keyword
Keyword Index
struct [struct-type-name]
{
[type variable-names] ;
...
} [structure-variables] ;
A struct, like an union, groups variables into a single record. The struct-type-name is an optional tag name that refers to the structure type. The structure-
variables are the data definitions, and are also optional. Though both are optional, one of the two must appear.
Elements in the record are defined by naming a type, followed by variable-names separated by commas. Different variable types can be separated by a
semicolon. For example,
struct my_struct
{
char name[80], phone_number[80];
int age, height;
} my_friend;
declares a record variable my_friend containing two strings (name and phone_number) and two integers (age and height). To declare additional variables of the
same type, you use the keyword struct followed by the struct-type-name, followed by the variable names. For example,
declares an array named my_friends which components are records. In fact, 'struct my_struct' becomes a new type which is equal in rights with any built-in
type.
To access elements in a structure, you use a record selector ('.'). For example,
A bit field is an element of a structure that is defined in terms of bits. Using a special type of struct definition, you can declare a structure element that can
range from 1 to 16 bits in length. For example,
struct bit_field
{
int bit_1 : 1;
int bits_2_to_5 : 4;
int bit_6 : 1;
int bits_7_to_16 : 10;
} bit_var;
typedef Keyword
Keyword Index
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 11 of 173
This statement assigns the symbol name identifier to the data type definition type-definition. For example,
byte m, n;
str40 myStr;
complex z1, z2;
byteptr p;
fncptr myFunc;
unsigned char m, n;
char myStr[41];
struct {float re, im;} z1, z2;
char *p;
int (*myFunc)(int);
User defined types may be used at any place where the built-in types may be used.
union Keyword
Keyword Index
A union is similar to a struct, except it allows you to define variables that share storage space. The syntax for defining unions is:
union [union-type-name]
{
type variable-names;
...
} [union-variables] ;
For example,
union short_or_long
{
short i;
long l;
} a_number;
The compiler will allocate enough storage in a number to accommodate the largest element in the union. Elements of a union are accessed in the same manner
as a struct.
Unlike a struct, the variables 'a_number.i' and 'a_number.l' occupy the same location in memory. Thus, writing into one will overwrite the other.
void Keyword
Keyword Index
When used as a function return type, void means that the function does not return a value. For example,
When found in a function heading, void means the function does not take any parameters. For example,
int init ()
{
return 1;
}
because in the second case the compiler will not check whether the function is really called with no arguments at all; instead, a function call with arbitrary
number of arguments will be accepted without any warnings (this is implemented only for the compatibility with the old-style function definition syntax).
Pointers can also be declared as void. They can't be dereferenced without explicit casting. This is because the compiler can't determine the size of the object the
pointer points to. For example,
int x;
float f;
void *p = &x; // p points to x
*(int*)p = 2;
p = &r; // p points to r
*(float*)p = 1.1;
volatile Keyword
Keyword Index
Keyword volatile is an extreme opposite of const. It indicates that a variable may be changed in a way which is absolutely unpredictable by analysing the
normal program flow (for example, a variable which may be changed by an interrupt handler). This keyword uses the following syntax:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 12 of 173
volatile data-definition;
Every reference to the variable will reload the contents from memory rather than take advantage of situations where a copy can be in a register.
while Keyword
Keyword Index
Keyword while is the most general loop statemens. It uses the following syntax:
statement is executed repeatedly as long as the value of expression remains nonzero. The test takes place before each execution of the statement. For
example,
{ } [ ] ( ) (type) . -> ++ --
& * + - ~ ! sizeof /
% << >> < > <= >= ==
!= ^ | && || ? : = *=
/= %= += -= <<= >>= &= ^=
|= , # ## ; : " " ...
In addition, GNU C also knows the typeof operator, and extends some existing operators.
Unary operators
Binary operators
Ternary operators
Punctuators
Depending on context, the same operator can have more than one meaning. For example, the ampersand ('&') can be interpreted as
In the first case, the '&' is a unary operator; in the second, the '&' is a binary operator. Similarly, the comma ',' may act as an operator and as a
punctuator, etc.
Unary operators
Note: In GNU C the operator '&&' may also be used as unary operator for taking addresses of labels.
In the expression
& expr
which means "take the address of the expr", the expr operand must be one of the following:
a function designator;
an lvalue designating an object that is not a bit field and is not declared with the register storage class specifier.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 13 of 173
In the expression
* expr
which means "the object pointed to by expr", the expr must have type "pointer to type," where type is any data type. The result of the indirection is of type
type.
If the operand is of type "pointer to function", the result is a function designator. If the operand is a pointer to an object, the result is an lvalue designating that
object.
You can also use the asterisk as an operator to dereference a pointer, or as the multiplication operator. Asterisk may be used also as a punctuator for creating
pointer types.
+ expr
- expr
the expr operand must be of arithmetic type. The result is the value of the operand after any required integral promotions for the unary plus ('+') operator, or
negative of the value of the operand after any required integral promotions for the unary minus ('-') operator. Floating point negation is internally executed
using the fneg function.
Note that both '+' and '-' operators also have a binary form.
expr ++ (postincrement)
++ expr (preincrement)
The expression is called the operand; it must be of scalar type (arithmetic or pointer types) and must be a modifiable lvalue.
When postincrement operator form is used, the value of the whole expression is the value of the postfix expression before the increment is applied. After the
postfix expression is evaluated, the operand is incremented by 1.
When preincrement operator form is used, the operand is incremented by 1 before the expression is evaluated; the value of the whole expression is the
incremented value of the operand.
The increment value is appropriate to the type of the operand. Pointer types follow the rules for pointer arithmetic. In other words, the actual address on which
a pointer points to is incremented by the size of the pointed object (not by 1, except if the pointed object is one byte long), so after the incrementing, the
pointer points to the next object in a sequence (e.g. to a next element in an array, etc.).
Note: GNU C extends the pointer arithmetic to be valid even on void pointers and pointers to functions (see extended pointer arithmetic for more info).
expr -- (postdecrement)
-- expr (predecrement)
The decrement operator follows the same rules as the increment operator, except that the operand is decremented by 1 after or before the whole expression is
evaluated.
In the expression
! expr
the expr operand must be of scalar type (i.e. not an array, a structure or an union). The result is of type int and is the logical negation of the operand:
In the expression
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 14 of 173
~ expr
the expr operand must be of integral type. The result is the bitwise complement of the operand after any required integral promotions. Each 0 bit in the
operand is set to 1, and each 1 bit in the operand is set to 0.
Binary operators
expr1 + expr2
expr1 - expr2
Note that both '+' and '-' operators also have an unary form.
In case 1, the operands are subjected to the standard arithmetical conversions (for example, chars are promoted to ints), and the result is the arithmetical
sum of the operands.
In cases 2 and 3, the rules of pointer arithmetic apply. When expr1 is of pointer type (case 2), the actual address on which a pointer points to is incremented
by expr2 multiplied by the size of the pointed object (not just by expr2, except if the pointed object is one byte long). For example, if expr1 points to an array,
expr1 + 5 points to a fifth element of the array, no matter how long are the particular elements of the array. The same rules are valid for the case 3. Assuming
that ptr is a pointer to type and that N is an integer, and assuming that the CPU uses linear addressing (this is true on Motorola 68000, but not on Intel 8086
for example), expression
ptr + N
is equal to
In case 1, the operands are subjected to the standard arithmetic conversions, and the result is the arithmetic difference of the operands.
In cases 2 and 3, the rules of pointer arithmetic apply. When expr1 is pointer and expr2 is integral type (case 2), the actual address on which a pointer points
to is decremented by expr2 multiplied by the size of the pointed object (not just by expr2, except if the pointed object is one byte long). For example, if expr1
points to the fifth element of an array, expr1 - 2 points to a third element of the array, no matter how long are the particular elements of the array. When both
expr1 and expr2 are pointers, the result of the substraction is the difference of actual addresses divided by the common size of pointed objects. For example, if
expr1 and expr2 point to two elements of the same array, then expr2 - expr1 will be equal to the difference of actual indices of pointed elements.
The unqualified type 'type' is considered to be compatible with the qualified types 'const type', 'volatile type', and 'const volatile type'.
Floating point addition and substraction are internally executed using the fadd and fsub functions.
Note: GNU C extends the pointer arithmetic to be valid even on void pointers and pointers to functions (see extended pointer arithmetic for more info).
expr1 * expr2
expr1 / expr2
expr1 % expr2
Note that '*' operator also has an unary form, and may be also used as a punctuator for creating pointer types.
Operands for '*' and '/' are of arithmetical type, and operands of '%' are of integral type. The usual arithmetic conversions are made on the operands. For
'/' and '%', expr2 must be nonzero; expr2 == 0 results in an error (you can't divide by zero).
When expr1 and expr2 are integers and the quotient is not an integer:
1. If expr1 and expr2 have the same sign, expr1 / expr2 is the largest integer less than the true quotient, and expr1 % expr2 has the sign of expr1.
2. If expr1 and expr2 have opposite signs, expr1 / expr2 is the smallest integer greater than the true quotient, and expr1 % expr1 has the sign of expr1.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 15 of 173
Floating point multiplication and division are internally executed using the fmul and fdiv functions; more detailed info about rules of these operation is given
with the description of these functions.
In the expressions expr1 << expr2 and expr1 >> expr2, the operands expr1 and expr2 must be of integral type. The normal integral promotions are performed
on expr1 and expr2, and the type of the result is the type of the promoted expr1. If expr2 is negative or is greater than or equal to the width in bits of expr1,
the operation is undefined.
The result of the operation expr1 << expr2 is the value of expr1 left-shifted by expr2 bit positions, zero-filled from the right if necessary. The result of the
operation expr1 >> expr2 is the value of expr1 right-shifted by expr2 bit positions.
Logical and bitwise operators ('&', '^', '|', '&&' and '||')
In first three expressions, both operands must be of integral type. In fourth and fifth expressions, both operands must be of scalar type. The usual arithmetical
conversions are performed on expr1 and expr2.
0 0 0 0 0
1 0 0 1 1
0 1 0 1 1
1 1 1 0 1
Unlike the bitwise operators, '&&' and '||' guarantee left-to-right evaluation. expr1 is evaluated first; if it is zero, expr1 && expr2 gives 0 (false), and expr2 is
not evaluated at all. With expr1 || expr2, if expr1 is nonzero, expr1 || expr2 gives 1 (true), and expr2 is not evaluated at all.
Note: In GNU C the operator '&&' may be also used as unary operator for taking addresses of labels.
There are 11 assignment operators in C language. The '=' operator is the simple assignment operator; the other 10 ('*=', '/=', '%=', '+=', '-=', '<<=',
'>>=', '&=', '^=' and '|=') are known as compound assignment operators. All of them use the following syntax:
In the expression expr1 = expr2, expr1 must be a modifiable lvalue. The value of expr2, after conversion to the type of expr1, is stored in the object
designated by expr1 (replacing expr1's previous value). The value of the assignment expression is the value of expr1 after the assignment. That's why multiple
assignments like
x = y = z = 10;
a = b + 2 * (c = d - 1);
are possible. Note that the assignment expression is not itself an lvalue.
For both simple and compound assignment, the operands expr1 and expr2 must obey one of the following sets of rules:
The compound assignments are 'op=', where op can be any one of the ten operator symbols '*', '/', '%', '+', '-', '<<', '>>', '&', '^' or '|'. The
expression
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 16 of 173
except that the lvalue expr1 is evaluated only once. For example, expr1 += expr2 is the same as expr1 = expr1 + expr2.
The relational operators are used to compare relative values. They use the following syntax:
In all relational expressions, the operands must conform to one of the following sets of conditions:
1. Both expr1 and expr2 are of arithmetic type. In this case, the usual arithmetic conversions are performed and the result is of type int.
2. Both expr1 and expr1 are pointers to qualified or unqualified versions of compatible object types.
expr1 < expr2 gives 1 (true) if the value of expr1 is less than value of expr2; otherwise, the result is 0 (false).
expr1 <= expr2 gives 1 (true) if the value of expr1 is less than or equal to the value of expr2; otherwise, the result is 0 (false).
expr1 > expr2 gives 1 (true) if the value of expr1 is greater than the value of expr2; otherwise, the result is 0 (false).
expr1 >= expr2 gives 1 (true) if the value of expr1 is greater than or equal to the value of expr2; otherwise, the result is 0 (false).
When the operands are of compatible pointer types, the result depends on the relative addresses of the two objects being pointed at.
Floating point comparisons are internally executed using the fcmp function. See the description of this function for more info about rules of comparisons for
floating point values.
The operators '==' and '!=' are used to test for equality or inequality between arithmetic or pointer values, following rules similar to those for the relational
operators. However, the equality operators have lower precedence than the relational operators, and you can also compare certain pointer types not allowed
with relational operations.
In the expressions expr1 == expr2 and expr1 != expr2, the operands must conform to one of the following sets of conditions:
If expr1 and expr2 have types that are valid operand types for a relational operator, the same comparison rules as for the relational operators apply.
If expr1 and expr2 are pointers to function types, expr1 == expr2 gives 1 (true) if they are both null or if they both point to the same function. Conversely, if
expr1 == expr2 gives 1 (true), then either expr1 and expr2 point to the same function, or they are both null.
The expression expr1 != expr2 follows the same rules, except that the result is 1 (true) if the operands are unequal, and 0 (false) if the operands are equal.
Floating point comparisons are internally executed using the fcmp function. See the description of this function for more info about rules of comparisons for
floating point values.
You use the selection operators '.' and '->' to access structure and union members. Suppose that the object s is of struct type S and sptr is a pointer to s.
Then, if m is a member identifier of type M declared in S, these expressions:
s.m
sptr->m
The expression
sptr->m
expresssion . identifier
The expr must be of type union or structure. The identifier must be the name of a member of that structure or union type.
The expr must be of type pointer to structure or pointer to union. The identifier must be the name of a member of that structure or union type.
The expression with selection operators designates a member of a structure or union object. The value of the selection expression is the value of the selected
member; it will be an lvalue if and only if the expr is an lvalue. For example,
struct mystruct
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 17 of 173
{
int i;
char str[21];
long d;
} s, *sptr=&s;
...
The expression 's.m' is an lvalue, provided that 's' is an lvalue and 'm' is not an array type. The expression 'sptr->m' is an lvalue unless 'm' is an array
type.
If structure B contains a field whose type is structure A, the members of A can be accessed by two applications of the member selectors.
Ternary operators
Ternary operators
The conditional operator '?:' is, in fact, a ternary operator. It uses the following syntax:
In the expression expr1 ? expr2 : Expr3, the operand expr1 must be of scalar type. The operands expr2 and Expr3 must obey one of the following sets of rules:
1. Both of arithmetic type. In this case, both expr2 and Expr3 are subject to the usual arithmetic conversions, and the type of the result is the common type
resulting from these conversions.
2. Both of compatible structure or union types. In this case, the type of the result is the structure or union type of expr2 and expr3.
3. Both of void type. In this case, the result is of type void.
4. Both of type pointer to qualified or unqualified versions of compatible types. In this case, the type of the result is pointer to a type qualified with all the
type qualifiers of the types pointed to by both operands.
5. One operand of pointer type, the other a null pointer constant In this case, the type of the result is pointer to a type qualified with all the type qualifiers of
the types pointed to by both operands.
6. One operand of type pointer to an object, the other of type pointer to a qualified or unqualified version of void. In this case, the type of the result is that
of the non-pointer-to-void operand.
In all cases, expr1 is evaluated first. If its value is nonzero (true), then expr2 is evaluated and expr3 is ignored (not evaluated at all). If expr1 evaluates to zero
(false), then expr3 is evaluated and expr2 is ignored. The result of expr1 ? expr2 : expr3 will be the value of whichever of expr2 and expr3 is evaluated.
Note: GNU C extends the usage of the conditional operator to allow omitting the middle operand, so it may be used as a binary operator too.
Punctuators
Punctuators Next
Brackets indicate single and multidimensional array subscripts. When used as an operator, the expression
expr1[expr2]
is defined exactly as
*((expr1) + (expr2))
where either expr1 is a pointer and expr2 is an integer, or expr1 is an integer and expr2 is a pointer. Of course, the addition is performed in according to the
pointer arithmetic rules (see binary plus for more info).
Note that every array name, if used alone (without the array subscript operator), is automatically interpreted as a pointer to the first element of the array.
When used as a punctuator, brackets are used for creating array types (see asterisk for more info).
Note: The GNU C extends the usage of square brackets to allow labeling elements in initializers.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 18 of 173
Note that parentheses are also the part of the TypeCast operator.
expr (arg-expression-list)
This is a call to the function given by the expr, which can be either the function name, or an expression which evaluates to a pointer-to-function type. In the
second case, the function call is in fact translated to
(* expr) (arg-expression-list)
arg-expression-list is a comma-delimited list of expressions of any type representing the actual (or real) function arguments. The value of the function call
expression, if it has a value, is determined by the return statement in the function definition.
arg-expression-list may even be empty, which is necessary when you need to call an argument-less function:
expr ()
Note that every function name, if used alone (without the parentheses operator), is automatically interpreted as a pointer to the function.
When used as a punctuator, parentheses are used for creating function types (see asterisk for more info).
Braces ('{...}')
The { } braces indicate the start and end of a compound statement. Each sequence of statements (terminated by semicolons) is treated as a single statement,
called compound statement. Compound statements may have its own local variables as well.
Braces are also used in declaration of enumerations, structures and unions, as well as for function definitions. For example:
Note: The GNU C extends the usage of braces (together with parentheses) to allow making statement expressions. They are also used in cast constructors,
which are yet another GNU C extension.
The '=' (equal sign) used as a punctuator separates variable declarations from initialization lists. For example,
int array[5] = { 1, 2, 3, 4, 5 };
char *name = "Fred";
int x = 12;
In a C function, no code can precede any variable declarations. Note that the GNU C, in opposite to other C dialects, allow non-constant initializers (like in
C++).
a = b + c;
or even:
a = b + 2 * (c = d - 1);
Note: The GNU C extends the usage of equal sign (as a punctuator) to allow labeling elements in initializers.
The comma, used as a punctuator, separates the elements of a function argument list, the elements in array or struct initializers, or the variables in a data
declaration. The comma is also used as an operator in comma expressions. Mixing the two uses of comma is legal, but you must use parentheses to distinguish
them.
When used as an operator, the comma operator uses the following syntax:
expr1, expr2
The left operand expr1 is evaluated as a void expression (i.e. it is ignored if not contain side effects), then expr2 is evaluated to give the result and type of the
comma expression. So, the result is just expr2. By recursion, the expression
results in the left-to-right evaluation of each Expr-i, with the value and type of ExprN giving the result of the whole expression. Comma operator is usually used
in for-loops for multiple initializations. For example,
It also may be used to avoid making compound statements in simple conditional statements. For example,
if (x > 10) i = 1, j = 2, k = 3;
if (x > 10)
{
i = 1; j = 2; k = 3;
}
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 19 of 173
To avoid ambiguity with the commas used in function argument and initializer lists, parentheses must be used. For example,
calls 'func' with three arguments, not four. The arguments are 'i', '5', and 'k'.
Semicolon (';')
The semicolon is a statement terminator. It is also used to separate three expressions which are parts of a for-loop.
Any legal C expression (including the empty expression) followed by ; is interpreted as a statement, known as an expression statement. The expression is
evaluated and its value is discarded. If the expression statement has no side effects, it will be simply ignored.
Semicolons are often used to create an empty statement. For example, the body of the following for-loop (which searches for a first non-zero element in the
array) is an empty statement:
Colon (':')
start:
x=0;
...
goto start;
Special case of labels are case-labels, which are used in multiple selection statements, for example,
switch (a)
{
case 1:
puts("One");
break;
case 2:
puts("Two");
break;
...
default:
puts("None of the above!");
}
Note: The GNU C allows creating of local labels, which are useful in macro definitions.
Asterisk ('*')
The asterisk ('*') in a variable expression creates a pointer to a type. For example,
int a, *b;
Punctuators asterisk, brackets and parentheses may be mixed together to create very complex data types (which are sometimes very hard to understand).
When mixed together, parentheses have the greatest precedence, then brackets, and finally, asterisks. This will be illustrated with a set of examples, which are
given in the following table:
int x[5][6]; An array (with 5 elements) of arrays (with 6 elements) of integers; such "array of arrays" may be interpreted as a 5x6 matrix
int x(); A function (more precise, a prototype of a function) which returns an integer
int x(int a); A function which accepts one integer argument, and which returns an integer
int x(int a,int *b); A function which accepts two arguments, the first one is an integer, and second one is a pointer to an integer, and which
returns an integer
int x(int,int*); The same as above, but actual names of arguments may be omitted in function prototypes (but not in function definitions)
int *x(int); A function which accepts one integer argument, and which returns a pointer to an integer
int **x; A pointer to a pointer to an integer (this declaration is logically equivalent with the next one)
int *x[]; An array of unknown size of pointers to integers (this declaration is logically equivalent with the previous one)
int (*x)(int,int); A pointer to a function which accepts two integer arguments and which returns an integer
int (*x(*x())[5])(); A function which returns a pointer to an array of pointers to a function which returns an integer
int (*x(*x(int))[5])(int*); A function which accepts one argument which is a pointer to an integer, and which returns a pointer to an array of pointers to
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 20 of 173
a function which accepts one integer argument and which returns an integer
int (*(*x[5])())[6]; An array (with 6 elements) of pointers to a function which returns a pointer to an array (with 5 elements) of integers
If you simply omit the actual variable name, you will get an anonymous type. Such anonymous types may be used with sizeof or typecast operators, or in lists
of arguments in function prototypes. For example, 'int*' is anonymous pointer to an integer, 'int(*)()' is anonymous pointer to a function which returns an
integer, and 'int(*[])(int*)' is anonymous array (of unknown size) of pointers to a function which returns an integer and which accepts one argument which
is a pointer to an integer.
Note: The GNU C extends the usage of asterisk to allow computed goto.
Quotes ('"..."')
Quotes are used for defining string constants. In the compile-time, the sequence of characters between qoutes are stored somewhere in the executable file. In
the run time, the "result" of quotes is a pointer (of type 'char*') which points to the place where the sequence of characters is stored. This interpretation of
quotes differs significantly from the interpretation of strings in other languages. That's why there is nothing wrong with the following C code (it stores the
address where the text "Hello" is stored, interpreted as an integer, in a):
int a;
a = (int)"Hello";
Such constructs are usually impossible in other languages. Note that sequences of characters between quotes behave similarly like arrays declared with the
static keyword, i.e. they can survive the end of a function or program if they are changed somewhere in the program (anyway, it is very bad idea to change the
content of a string constant). For example, the following code
will display "xyzayz", although it seems that "xyzxyz" would be displayed. Such strange behaviour is caused by the fact that "xyz" is initialized in the compile-
time. Now, if you understand the correct interpretation of what the quote punctuator does, you can explain this behaviour easily. To learn: strings in C behave
quite differently than in most other languages!
Note: These two statements are very different, although most books say that they are nearly the same:
Suppose that str is declared in the body of the function (i.e. it is an automatic local variable). In both cases, the text "Hello" is stored somewhere in memory,
and the "result" of "Hello" is the address where it is stored (we will call this address addr). In the first case, str is a local array (i.e. it is created on the stack at
run time, and there will be 6 bytes reserved for it), whose content is initialized at run-time (because it does not exist at compile-time) with the sequence of
bytes located at addr. In other words, it is the same as you wrote:
char str[6];
strcpy (str, "Hello");
The consequence is that if you change the content of str (note that this is not the same as changing bytes pointed to by addr), it will be reinitialized each time
when this statement is encountered again. But, in the second case, str is a local pointer, whose content is initialized (at run-time) with addr! So, if the contents
of the string "Hello" are changed, this change will be permanent, because when this statement is encountered again, str will simply be reinitialized (if changed)
to addr but bytes pointed to by it are not restored! Confused? See the following code:
This program will work as expected (it will display "Hello" twice). But, if you change 'str[]' to '*str', it will not work as expected (it will display "Hello" and
then "aello").
Generally, it is a very bad idea to change strings which are the result of quotes. The reason is that usually equal strings are stored only once in the program.
This means that you can get unexpected results if you modify them.
If the '\' character is found inside a string literal, it is threated as the start of an escape code. Here is an incomplete list of possible escape codes:
\" Represents one '"' character. Needed in strings to represent this character, because an unescaped '"' would end the string.
\xdd... A hex character code. All trailing hex digits are combined.
Ellipsis ('...')
An ellipsis ('...') consists of three successive periods with no whitespace intervening. You can use an ellipsis in the formal argument lists of function
prototypes to indicate a variable number of arguments, or arguments with varying types. For example,
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 21 of 173
This declaration indicates that func will be defined in such a way that calls must have at least two arguments, an int and a char, but can also have any number
of additional arguments.
Note: The GNU C extends the usage of ellipsis for making case ranges and for labeling elements in initializers.
Typecast ('(type)')
Previous Punctuators
The typecast operator forces an expression to behave as an object of a given type. It uses the following syntax:
(type) expr
The expression expr will be interpreted as having type type. It may be any simple type (modified or unmodified), enumeration, structure, union, user defined
type created using typedef, void type, or an anonymous type (see asterisk for more information about anonymous types). Here is an example list of valid
typecast operators:
(int)
(unsigned long int)
(signed)
(enum foo)
(struct foo)
(mytype) assuming that 'mytype' is defined with 'typedef'
(void)
(char *)
(void *)
(struct foo *)
(void (*)(int))
(int (*[])(char*))
Typecast operator is very powerful in C, and may be used for conversion nearly everything to anything. For example, it is legal to convert an integer value to a
pointer, so you can perform direct access to the memory (don't do this if you don't know exactly what are you doing). For example, '(char*)19456' converts
integer 19456 to a char pointer, which may be dereferenced further using the dereference operator. So,
* (char*)19456 = 255;
stores 255 in the memory at the absolute address 19456 (this is the first byte of the LCD memory on TI-89 and TI-92+). The more drastic example is
((void(*)())10000)();
which calls the subroutine located at absolute address 10000 (first, the typecast operator '(void(*)())' converts 10000 to the pointer to the function, then
the parentheses operator '()' is used to call the function). Note that nearly the whole TIGCC library, when used in "nostub" mode, is implemented using the
typecast operator which converts TIOS jump table entries to pointers to functions. For example, ClrScr is defined as '(*(void(**)(void))(*(long*)
0xC8+0x678))', which is nothing other than a complex typecast. So, when you do
ClrScr ();
(*(void(**)(void))(*(long*)0xC8+0x678))();
However, typecast operator cannot be used to convert a scalar type to a structure or union (and vice versa), or to convert one non-scalar type into an
incompatible non-scalar type. That's why casting to structures and unions are rarely valid.
Casting to a void means that you want to discard the result of the expression.
Casting to or from a floating point type are internally executed using the flt and trunc functions. See the description of these functions for more info.
Note: GNU C extends the usage of typecast operator to allow making cast constructors, which are probably the most powerful GNU C extensions. It also allows
much more flexibility in casting to an union types.
Precedence of Operators
In the following table of operator precedence, the C operators are divided into 15 categories. The #1 category has the highest precedence; category #2 (Unary
operators) takes second precedence, and so on to the Comma operator, which has lowest precedence. The operators within each category have equal
precedence.
The Unary (category #2), Conditional (category #13), and Assignment (category #14) operators associate right-to-left; all other operators associate left-to-
right.
3. Multiplicative * Multiply
/ Divide
% Remainder (modulus)
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 22 of 173
7. Equality == Equal to
!= Not equal to
9. ^ Bitwise XOR
10. | Bitwise OR
12. || Logical OR
An lvalue is an object locator: an expression that designates an object. Any variable is an lvalue for example. Another example of an lvalue expression is '*P',
where P is any expression evaluating to a non-null pointer. See dereference operator for more information.
A modifiable lvalue is an identifier or expression that relates to an object that can be accessed and legally changed in memory. A const pointer to a constant,
for example, is not a modifiable lvalue. A pointer to a constant can be changed (but its dereferenced value cannot).
Historically, the "l" stood for "left", meaning that an lvalue could legally stand on the left (the receiving end) of an assignment statement. Now, only modifiable
lvalues can legally stand on the left of an assignment statement. For example, if 'a' and 'b' are nonconstant integer identifiers with properly allocated
memory storage, they are both modifiable lvalues, and assignments such as
a = 1;
b = a + b;
a + b
is not an lvalue: 'a + b = a' is illegal because the expression on the left is not related to an object. Such expressions are often called rvalues (short for "right
values").
Note: In GNU C, the class of lvalue expressions is wider than in other C dialects; see section Generalized Lvalues for more info.
This part of the documentation is a modified version of the C Extensions section of the GCC Manual. Therefore it is licensed under the GNU Free Documentation
License.
TIGCC (like all GNU C compilers) provides several language features not found in ISO standard C. To test for the availability of these features in conditional
compilation, check for a predefined macro __GNUC__, which is always defined under GCC.
Some features that are in ISO C99 but not C89 are also, as extensions, accepted by GCC in C89 mode.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 23 of 173
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version
published by the Free Software Foundation; with the Invariant Sections being "GNU General Public License" and "Funding Free Software", the Front-Cover texts
being (a) (see below), and with the Back-Cover Texts being (b) (see below). A copy of the license is included in the section entitled "GNU Free Documentation
License".
A GNU Manual
You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development.
A compound statement enclosed in parentheses may appear as an expression in GNU C. This allows you to use loops, switches, and local variables within an
expression.
Recall that a compound statement is a sequence of statements surrounded by braces; in this construct, parentheses go around the braces. For example:
is a valid (though slightly more complex than necessary) expression for the absolute value of foo ().
The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire
construct. (If you use some other kind of statement last within the braces, the construct has type void, and thus effectively no value.)
This feature is especially useful in making macro definitions "safe" (so that they evaluate each operand exactly once). For example, the "maximum" function is
commonly defined as a macro in standard C as follows:
But this definition computes either a or b twice, with bad results if the operand has side effects. In GNU C, if you know the type of the operands (here let's
assume int), you can define the macro safely as follows:
#define maxint(a,b) \
({int _a = (a), _b = (b); _a > _b ? _a : _b; })
Embedded statements are not allowed in constant expressions, such as the value of an enumeration constant, the width of a bit-field, or the initial value of a
static variable.
If you don't know the type of the operand, you can still do this, but you must use typeof.
Each statement expression is a scope in which local labels can be declared. A local label is simply an identifier; you can jump to it with an ordinary goto
statement, but only from within the statement expression it belongs to.
__label__ label;
or
Local label declarations must come at the beginning of the statement expression, right after the ({, before any ordinary declarations.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 24 of 173
The label declaration defines the label name, but does not define the label itself. You must do this in the usual way, with label:, within the statements of the
statement expression.
The local label feature is useful because statement expressions are often used in macros. If the macro contains nested loops, a goto can be useful for breaking
out of them. However, an ordinary label whose scope is the whole function cannot be used: if the macro can be expanded several times in one function, the
label will be multiply defined in that function. A local label avoids this problem. For example:
Labels as Values
You can get the address of a label defined in the current function (or a containing function) with the unary operator &&. The + value has type void*. This value
is a constant and can be used wherever a constant of that type is valid. For example:
void *ptr;
/* ... */
ptr = &&foo;
To use these values, you need to be able to jump to one. This is done with the computed goto statement, goto *exp;. For example,
goto *ptr;
One way of using these constants is in initializing a static array that will serve as a jump table:
goto *array[i];
Note that this does not check whether the subscript is in bounds - array indexing in C never does that.
Such an array of label values serves a purpose much like that of the switch statement. The switch statement is cleaner, so use that rather than an array
unless the problem does not fit a switch statement very well.
You may not use this mechanism to jump to code in a different function. If you do that, totally unpredictable things will happen. The best way to avoid this is to
store the label address only in automatic variables and never pass it as an argument.
This is more friendly to code living in shared libraries (DLLs), as it reduces the number of dynamic relocations that are needed (and, by consequence, would
allow the data to be read-only).
Nested Functions
A nested function is a function defined inside another function. The nested function's name is local to the block where it is defined. For example, here we define
a nested function named square, and call it twice:
The nested function can access all the variables of the containing function that are visible at the point of its definition. This is called lexical scoping. For
example, here we show a nested function which uses an inherited variable named offset:
int i;
/* ... */
for (i = 0; i < size; i++)
/* ... */ access (array, i) /* ... */
}
Nested function definitions are permitted within functions in the places where variable definitions are allowed; that is, in any block, before the first statement in
the block.
It is possible to call the nested function from outside the scope of its name by storing its address or passing the address to another function:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 25 of 173
Here, the function intermediate receives the address of store as an argument. If intermediate calls store, the arguments given to store are used to store
into array. But this technique works only so long as the containing function (hack, in this example) does not exit.
If you try to call the nested function through its address after the containing function has exited, all hell will break loose. If you try to call it after a containing
scope level has exited, and if it refers to some of the variables that are no longer in scope, you may be lucky, but it's not wise to take the risk. If, however, the
nested function does not refer to anything that has gone out of scope, you should be safe.
GCC implements taking the address of a nested function using a technique called trampolines. A paper describing them is available at
http://people.debian.org/~aaronl/Usenix88-lexic.pdf. Note that trampolines are currently broken in TIGCC; they create code on the stack, which can make HW2
calculators crash.
A nested function can jump to a label inherited from a containing function, provided the label was explicitly declared in the containing function (see Local
Labels). Such a jump returns instantly to the containing function, exiting the nested function which did the goto and any intermediate functions as well. Here is
an example:
A nested function always has internal linkage. Declaring one with extern is erroneous. If you need to declare the nested function before its definition, use auto
(which is otherwise meaningless for function declarations).
Using the built-in functions described below, you can record the arguments a function received, and call another function with the same arguments, without
knowing the number or types of the arguments.
You can also record the return value of that function call, and later return that value, without knowing what data type the function tried to return (as long as
your caller expects that data type).
__builtin_apply_args
__builtin_apply
__builtin_return
__builtin_apply_args
This built-in function returns a pointer to data describing how to perform a call with the same arguments as were passed to the current function.
The function saves the arg pointer register, structure value address, and all registers that might be used to pass arguments to a function into a block of
memory allocated on the stack. Then it returns the address of that block.
__builtin_apply
This built-in function invokes function with a copy of the parameters described by arguments and size.
The value of arguments should be the value returned by __builtin_apply_args. The argument size specifies the size of the stack argument data, in bytes.
This function returns a pointer to data describing how to return whatever value was returned by function. The data is saved in a block of memory allocated on
the stack.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 26 of 173
It is not always simple to compute the proper value for size. The value is used by __builtin_apply to compute the amount of data that should be pushed on the
stack and copied from the incoming argument area.
__builtin_return
This built-in function returns the value described by result from the containing function. You should specify, for result, a value returned by __builtin_apply.
Another way to refer to the type of an expression is with typeof. The syntax of using of this keyword looks like sizeof, but the construct acts semantically like
a type name defined with typedef.
There are two ways of writing the argument to typeof: with an expression or with a type. Here is an example with an expression:
typeof (x[0](1))
This assumes that x is an array of pointers to functions; the type described is that of the values of the functions.
typeof (int *)
A typeof-construct can be used anywhere a typedef name could be used. For example, you can use it in a declaration, in a cast, or inside of sizeof or typeof.
typeof is often useful in conjunction with the statements-within-expressions feature. Here is how the two together can be used to define a safe "maximum"
macro that operates on any arithmetic type and evaluates each of its arguments exactly once:
#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
The reason for using names that start with underscores for the local variables is to avoid conflicts with variable names that occur within the expressions that are
substituted for a and b. Eventually we hope to design a new form of declaration syntax that allows you to declare variables whose scopes start only after their
initializers; this will be a more reliable way to prevent such conflicts.
typeof (*x) y;
char *y[4];
To see the meaning of the declaration using typeof, and why it might be a useful way to write, let's rewrite it with these macros:
Compatibility Note: In addition to typeof, GCC 2 supported a more limited extension which permitted one to write
typedef T = expr;
with the effect of declaring T to have the type of the expression expr. This extension does not work with GCC 3 (versions between 3.0 and 3.2 will crash; 3.2.1
and later give an error). Code which relies on it should be rewritten to use typeof:
typedef typeof(expr) T;
Generalized Lvalues
Compound expressions, conditional expressions and casts are allowed as lvalues provided their operands are lvalues. This means that you can take their
addresses or store values into them.
For example, a compound expression can be assigned, provided the last expression in the sequence is an lvalue. These two expressions are equivalent:
(a, b) += 5
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 27 of 173
a, (b += 5)
Similarly, the address of the compound expression can be taken. These two expressions are equivalent:
&(a, b)
a, &b
A conditional expression is a valid lvalue if its type is not void and the true and false branches are both valid lvalues. For example, these two expressions are
equivalent:
(a ? b : c) = 5
(a ? b = 5 : (c = 5))
A cast is a valid lvalue if its operand is an lvalue. A simple assignment whose left-hand side is a cast works by converting the right-hand side first to the
specified type, then to the type of the inner left-hand side expression. After this is stored, the value is converted back to the specified type to become the value
of the assignment. Thus, if a has type char*, the following two expressions are equivalent:
(int)a = 5
(int)(a = (char *)(int)5)
An assignment-with-arithmetic operation such as += applied to a cast performs the arithmetic using the type resulting from the cast, and then continues as in
the previous case. Therefore, these two expressions are equivalent:
(int)a += 5
(int)(a = (char *)(int) ((int)a + 5))
You cannot take the address of an lvalue cast, because the use of its address would not work out coherently. Suppose that &(int)f were permitted, where f
has type float. Then the following statement would try to store an integer bit-pattern where a floating point number belongs:
*&(int)f = 1;
This is quite different from what (int)f = 1 would do - that would convert 1 to floating point and store it. Rather than cause this inconsistency, the GNU team
thinks it is better to prohibit use of & on a cast.
If you really do want an int* pointer with the address of f, you can simply write (int*)&f.
The middle operand in a conditional expression may be omitted. Then if the first operand is nonzero, its value is the value of the conditional expression.
x ? : y
x ? x : y
In this simple case, the ability to omit the middle operand is not especially useful. When it becomes useful is when the first operand does, or may (if it is a
macro argument), contain a side effect. Then repeating the operand in the middle would perform the side effect twice. Omitting the middle operand uses the
value already computed without the undesirable effects of recomputing it.
Double-Word Integers
ISO C99 supports data types for integers that are at least 64 bits wide, and as an extension GCC supports them in C89 mode. Simply write long long int for
a signed integer, or unsigned long long int for an unsigned integer. To make an integer constant of type long long int, add the suffix LL to the integer. To
make an integer constant of type unsigned long long int, add the suffix ULL to the integer.
You can use these types in arithmetic like any other integer types. Addition, subtraction, and bitwise boolean operations on these types are open-coded on all
types of machines, as well as shifts with a constant value. Multiplication, division and shifts are not open-coded and use special library routines.
There may be pitfalls when you use long long types for function arguments, unless you declare function prototypes. If a function expects type int for its
argument, and you pass a value of type long long int, confusion will result because the caller and the subroutine will disagree about the number of bytes for
the argument. Likewise, if the function expects long long int and you pass int. The best way to avoid such problems is to use prototypes.
Complex Numbers
ISO C99 supports complex floating data types, and as an extension GCC supports them in C89 mode, and supports complex integer data types which are not
part of ISO C99. You can declare complex types using the keyword _Complex. As an extension, the older GNU keyword __complex__ is also supported.
For example, _Complex double x; declares x as a variable whose real part and imaginary part are both of type double. _Complex short int y; declares y to
have real and imaginary parts of type short int; this is not likely to be useful, but it shows that the set of complex types is complete.
To write a constant with a complex data type, use the suffix i or j (either one; they are equivalent). For example, 2.5fi has type _Complex float and 3i has
type _Complex int. Such a constant always has a pure imaginary value, but you can form any complex value you like by adding one to a real constant. This is
a GNU extension; once TIGCC supports this, you should include <complex.h> and use the macros I or _Complex_I instead.
To extract the real part of a complex-valued expression exp, write __real__ exp. Likewise, use __imag__ to extract the imaginary part. This is a GNU
extension; for values of floating type, you should use the ISO C99 functions crealf, creal, creall, cimagf, cimag and cimagl, declared in <complex.h> (not
yet available in TIGCC) and also provided as built-in functions by GCC.
The operator ~ performs complex conjugation when used on a value with a complex type. This is a GNU extension; for values of floating type, you should use
the ISO C99 functions conjf, conj and conjl, declared in <complex.h> and also provided as built-in functions by GCC.
GCC can allocate complex automatic variables in a noncontiguous fashion; it's even possible for the real part to be in a register while the imaginary part is on
the stack (or vice-versa).
Hex Floats
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 28 of 173
ISO C99 supports floating-point numbers written not only in the usual decimal notation, such as 1.55e1, but also numbers such as 0x1.fp3 written in
hexadecimal format. As a GNU extension, GCC supports this in C89 mode (except in some cases when strictly conforming). In that format the 0x hex introducer
and the p or P exponent field are mandatory. The exponent is a decimal number that indicates the power of 2 by which the significant part will be multiplied.
Thus 0x1.f is 1 15/16, p3 multiplies it by 8, and the value of 0x1.fp3 is the same as 1.55e1.
Unlike for floating-point numbers in the decimal notation the exponent is always required in the hexadecimal notation. Otherwise the compiler would not be able
to resolve the ambiguity of, e.g., 0x1.f. This could mean 1.0f or 1.9375 since f is also the extension for floating-point constants of type float.
Binary Numbers
TIGCC allows you to specify binary numbers by using a 0b prefix. This can be handy in many occasions, such as when trying to declare sprites in a way which
actually allows you to see the picture. For example, the following declaration defines a simple black and white 8x8 diagonal cross:
struct empty {
};
The structure will have size zero. In C++, empty structures are part of the language, and the language standard says they have size 1.
Zero-length arrays are allowed in GNU C. They are very useful as the last element of a structure which is really a header for a variable-length object:
struct line {
int length;
char contents[0];
};
In ISO C90, you would have to give contents a length of 1, which means either you waste space or complicate the argument to malloc.
In ISO C99, you would use a flexible array member, which is slightly different in syntax and semantics:
Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length
arrays, sizeof evaluates to zero.
Flexible array members may only appear as the last member of a struct that is otherwise non-empty.
A structure containing a flexible array member, or a union containing such a structure (possibly recursively), may not be a member of a structure or an
element of an array. (However, these uses are permitted by GCC as extensions.)
GCC versions before 3.0 allowed zero-length arrays to be statically initialized, as if they were flexible arrays. In addition to those cases that were useful, it also
allowed initializations in situations that would corrupt later data. Non-empty initialization of zero-length arrays is now treated like any case where there are
more initializer elements than the array holds, in that a suitable warning about "excess elements in array" is given, and the excess elements (all of them, in this
case) are ignored.
Instead GCC allows static initialization of flexible array members. This is equivalent to defining a new structure containing the original structure followed by an
array of sufficient size to contain the data. I.e. in the following, f1 is constructed as if it were declared like f2.
struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };
struct f2 {
struct f1 f1; int data[3];
} f2 = { { 1 }, { 2, 3, 4 } };
The convenience of this extension is that f1 has the desired type, eliminating the need to consistently refer to f2.f1.
This has symmetry with normal static arrays, in that an array of unknown size is also written with [].
Of course, this extension only makes sense if the extra data comes at the end of a top-level object, as otherwise we would be overwriting data at subsequent
offsets. To avoid undue complication and confusion with initialization of deeply nested arrays, we simply disallow any non-empty initialization except when the
structure is the top-level object. For example:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 29 of 173
Variable-length automatic arrays are allowed in ISO C99, and as an extension GCC accepts them in C89 mode. (However, GCC's implementation of variable-
length arrays does not yet conform in detail to the ISO C99 standard.) These arrays are declared like any other automatic arrays, but with a length that is not a
constant expression. The storage is allocated at the point of declaration and deallocated when the brace-level is exited. For example:
FILE *concat_fopen (const char *s1, const char *s2, const char *mode)
{
char str[strlen (s1) + strlen (s2) + 1];
strcpy (str, s1);
strcat (str, s2);
return fopen (str, mode);
}
Jumping or breaking out of the scope of the array name deallocates the storage. Jumping into the scope is not allowed; you get an error message for it.
You can use the function alloca to get an effect much like variable-length arrays. The function alloca is available in many other C implementations (but not in
all). On the other hand, variable-length arrays are more elegant.
There are other differences between these two methods. Space allocated with alloca exists until the containing function returns. The space for a variable-length
array is deallocated as soon as the array name's scope ends. (If you use both variable-length arrays and alloca in the same function, deallocation of a variable-
length array will also deallocate anything more recently allocated with alloca.)
struct entry
tester (int len, char data[len][len])
{
/* ... */
}
The length of an array is computed once when the storage is allocated and is remembered for the scope of the array in case you access it with sizeof.
If you want to pass the array first and the length afterward, you can use a forward declaration in the parameter list - another GNU extension.
struct entry
tester (int len; char data[len][len], int len)
{
/* ... */
}
The int len before the semicolon is a parameter forward declaration, and it serves the purpose of making the name len known when the declaration of data is
parsed.
You can write any number of such parameter forward declarations in the parameter list. They can be separated by commas or semicolons, but the last one must
end with a semicolon, which is followed by the "real" parameter declarations. Each forward declaration must match a "real" declaration in parameter name and
data type. ISO C99 does not support parameter forward declarations.
In the ISO C standard of 1999, a macro can be declared to accept a variable number of arguments much as a function can. The syntax for defining the macro is
similar to that of a function. Here is an example:
Here ... is a variable argument. In the invocation of such a macro, it represents the zero or more tokens until the closing parenthesis that ends the invocation,
including any commas. This set of tokens replaces the identifier __VA_ARGS__ in the macro body wherever it appears. For more information, see Variadic
Macros.
GCC has long supported variadic macros, and used a different syntax that allowed you to give a name to the variable arguments just like any other argument.
Here is an example:
This is in all ways equivalent to the ISO C example above, but arguably more readable and descriptive.
GNU CPP has two further variadic macro extensions, and permits them to be used with either of the above forms of macro definition.
In standard C, you are not allowed to leave the variable argument out entirely; but you are allowed to pass an empty argument. For example, this invocation is
invalid in ISO C, because there is no comma after the string:
GNU CPP permits you to completely omit the variable arguments in this way. In the above examples, the compiler would complain, though since the expansion
of the macro still has the extra comma after the format string.
To help solve this problem, CPP behaves specially for variable arguments used with the token paste operator, ##. If instead you write
and if the variable arguments are omitted or empty, the ## operator causes the preprocessor to remove the comma before it. If you do provide some variable
arguments in your macro invocation, GNU CPP does not complain about the paste operation and instead places the variable arguments after the comma. Just
like any other pasted macro argument, these arguments are not macro expanded.
In ISO C99, arrays that are not lvalues still decay to pointers, and may be subscripted, although they may not be modified or used after the next sequence
point and the unary & operator may not be applied to them. As an extension, GCC allows such arrays to be subscripted in C89 mode, though otherwise they do
not decay to pointers outside C99 mode. For example, this is valid in GNU C though not valid in C89:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 30 of 173
In GNU C, addition and subtraction operations are supported on pointers to void and on pointers to functions. This is done by treating the size of a void or of a
function as 1.
A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.
Non-Constant Initializers
As in standard C++ and ISO C99, the elements of an aggregate initializer for an automatic variable are not required to be constant expressions in GNU C. Here
is an example of an initializer with run-time varying elements:
ISO C99 supports compound literals. A compound literal looks like a cast containing an initializer. Its value is an object of the type specified in the cast,
containing the elements specified in the initializer; it is an lvalue. As an extension, GCC supports compound literals in C89 mode and in C++.
Usually, the specified type is a structure. Assume that struct foo and structure are declared as shown:
{
struct foo temp = {x + y, 'a', 0};
structure = temp;
}
You can also construct an array. If all the elements of the compound literal are (made up of) simple constant expressions, suitable for use in initializers of
objects of static storage duration, then the compound literal can be coerced to a pointer to its first element and used in such an initializer, as shown here:
Compound literals for scalar types and union types are also allowed, but then the compound literal is equivalent to a cast.
As a GNU extension, GCC allows initialization of objects with static storage duration by compound literals (which is not possible in ISO C99, because the
initializer is not a constant). It is handled as if the object was initialized only with the bracket enclosed list if compound literal's and object types match. The
initializer list of the compound literal must be constant. If the object being initialized has array type of unknown size, the size is determined by compound literal
size.
Designated Initializers
Standard C89 requires the elements of an initializer to appear in a fixed order, the same as the order of the elements in the array or structure being initialized.
In ISO C99 you can give the elements in any order, specifying the array indices or structure field names they apply to, and GNU C allows this as an extension in
C89 mode as well.
To specify an array index, write [index] = before the element value. For example,
is equivalent to
The index values must be constant expressions, even if the array being initialized is automatic.
An alternative syntax for this which has been obsolete since GCC 2.5 but GCC still accepts is to write [index] before the element value, with no =.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 31 of 173
To initialize a range of elements to the same value, write [first ... last] = value. This is a GNU extension. For example,
If the value in it has side-effects, the side-effects will happen only once, not for each initialized field by the range initializer.
Note that the length of the array is the highest value specified plus one.
In a structure initializer, specify the name of a field to initialize with .fieldname = before the element value. For example, given the following structure,
is equivalent to
Another syntax which has the same meaning, obsolete since GCC 2.5, is fieldname:, as shown here:
The [index] or .fieldname is known as a designator. You can also use a designator (or the obsolete colon syntax) when initializing a union, to specify which
element of the union should be used. For example,
union foo f = { .d = 4 };
will convert 4 to a double to store it in the union using the second element. By contrast, casting 4 to type union foo would store it into the union as the
integer i, since it is an integer (see Cast to Union).
You can combine this technique of naming elements with ordinary C initialization of successive elements. Each initializer element that does not have a
designator applies to the next consecutive element of the array or structure. For example,
is equivalent to
Labeling the elements of an array initializer is especially useful when the indices are characters or belong to an enum type. For example:
int whitespace[256]
= { [' '] = 1, ['\t'] = 1, ['\h'] = 1,
['\f'] = 1, ['\n'] = 1, ['\r'] = 1 };
You can also write a series of .fieldname and [index] designators before an = to specify a nested subobject to initialize; the list is taken relative to the
subobject corresponding to the closest surrounding brace pair. For example, with the struct point declaration above:
If the same field is initialized multiple times, it will have value from the last initialization. If any such overridden initialization has side-effect, it is unspecified
whether the side-effect happens or not. Currently, GCC will discard them and issue a warning.
A cast to union type is similar to other casts, except that the type specified is a union type. You can specify the type either with union tag or with a typedef
name. A cast to union is actually a constructor though, not a cast, and hence does not yield an lvalue like normal casts (see Compound Literals).
The types that may be cast to the union type are those of the members of the union. Thus, given the following union and variables:
Using the cast as the right-hand side of an assignment to a variable of union type is equivalent to storing in a member of the union:
union foo u;
/* ... */
u = (union foo) x <=> u.i = x
u = (union foo) y <=> u.d = y
Case Ranges
You can specify a range of consecutive values in a single case label, like this:
This has the same effect as the proper number of individual case labels, one for each integer value from low to high, inclusive.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 32 of 173
Note: Always write spaces around the ..., for otherwise it may be parsed wrong when you use it with integer values. For example, write this:
case 1 ... 5:
case 1...5:
In GNU C, you declare certain things about functions called in your program which help the compiler optimize function calls and check your code more carefully.
The keyword __attribute__ allows you to specify special attributes when making a declaration. This keyword is followed by an attribute specification inside
double parentheses. The following attributes are currently defined for functions:
noreturn
pure
const
format
format_arg
no_instrument_function
section
constructor, destructor
unused
used
malloc
alias
always_inline
noinline
deprecated
regparm, stkparm
nonnull
nothrow
Other attributes are supported for variable declarations (see Variable Attributes) and for types (see Type Attributes).
TIGCC also defines the macros CALLBACK, __ATTR_TIOS__, __ATTR_TIOS_NORETURN__, __ATTR_TIOS_CALLBACK__, __ATTR_GCC__, __ATTR_LIB_C__,
__ATTR_LIB_ASM__, __ATTR_LIB_ASM_NORETURN__, __ATTR_LIB_CALLBACK_C__, and __ATTR_LIB_CALLBACK_ASM__. They are useful for specifying default
attributes for a specific class of functions. You only need to use them when you define a callback function. For example, the callback function type compare_t
needs the attributes specified by __ATTR_LIB_CALLBACK_C__, i.e. the attributes required by a callback function for a library function written in C. Since this is
too inconvenient for the user, all three callback attributes have been made equal, and we have defined a single CALLBACK macro.
You may also specify attributes with __ preceding and following each keyword. This allows you to use them in header files without being concerned about a
possible macro of the same name. For example, you may use __noreturn__ instead of noreturn. For example, as malloc is defined as a macro in the TIGCC
Library, always use __malloc__ instead of malloc.
See Attribute Syntax for details of the exact syntax for using attributes.
You can specify multiple attributes in a declaration by separating them by commas within the double parentheses or by immediately following an attribute
declaration with another attribute declaration.
Some people object to the __attribute__ feature, suggesting that ISO C's #pragma should be used instead. At the time __attribute__ was designed, there
were two reasons for not doing this.
2. There is no telling what the same #pragma might mean in another compiler.
These two reasons applied to almost any application that might have been proposed for #pragma. It was basically a mistake to use #pragma for anything.
The ISO C99 standard includes _Pragma, which now allows pragmas to be generated from macros. In addition, a #pragma GCC namespace is now in use for
GCC-specific pragmas. However, it has been found convenient to use __attribute__ to achieve a natural attachment of attributes to their corresponding
declarations, whereas #pragma GCC is of use for constructs that do not naturally form part of the grammar.
noreturn
A few standard library functions, such as abort and exit, cannot return. Some programs define their own functions that never return. You can declare them
noreturn to tell the compiler this fact. For example:
void
fatal (/* ... */)
{
/* ... */ /* Print error message. */ /* ... */
exit (1);
}
The noreturn keyword tells the compiler to assume that fatal cannot return. It can then optimize without regard to what would happen if fatal ever did return.
This makes slightly better code. More importantly, it helps avoid spurious warnings of uninitialized variables.
Do not assume that registers saved by the calling function are restored before calling the noreturn function.
It does not make sense for a noreturn function to have a return type other than void.
pure
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 33 of 173
Many functions have no effects except the return value and their return value depends only on the parameters and/or global variables. Such a function can be
subject to common subexpression elimination and loop optimization just as an arithmetic operator would be. These functions should be declared with the
attribute pure. For example,
says that the hypothetical function square is safe to call fewer times than the program says.
Some common examples of pure functions are strlen or memcmp. Interesting non-pure functions are functions with infinite loops or those depending on volatile
memory or other system resource, that may change between two consecutive calls.
const
Many functions do not examine any values except their arguments, and have no effects except the return value. Basically this is just slightly more strict class
than the pure attribute, since the function is not allowed to read global memory.
Note that a function that has pointer arguments and examines the data pointed to must not be declared const. Likewise, a function that calls a non-const
function usually must not be const. It does not make sense for a const function to return void.
format
The format attribute specifies that a function takes printf style arguments which should be type-checked against a format string. For example, the declaration:
extern int
my_printf (void *my_object, const char *my_format, ...)
__attribute__ ((format (printf, 2, 3)));
causes the compiler to check the arguments in calls to my_printf for consistency with the printf style format string argument my_format.
The parameter archetype determines how the format string is interpreted, and should be printf, scanf, strftime or strfmon (note that only the function
printf is implemented in the TIGCC Library). (You can also use __printf__, __scanf__, __strftime__ or __strfmon__.) The parameter string-index specifies
which argument is the format string argument (starting from 1), while first-to-check is the number of the first argument to check against the format string. For
functions where the arguments are not available to be checked (such as vprintf), specify the third parameter as zero. In this case the compiler only checks the
format string for consistency. For strftime formats, the third parameter is required to be zero.
In the example above, the format string (my_format) is the second argument of the function my_print, and the arguments to check start with the third
argument, so the correct parameters for the format attribute are 2 and 3.
The format attribute allows you to identify your own functions which take format strings as arguments, so that GCC can check the calls to these functions for
errors. The compiler always (unless '-ffreestanding' is used) checks formats for the standard library functions. See Options Controlling C Dialect.
format_arg
The format_arg attribute specifies that a function takes a format string for a printf style function and modifies it (for example, to translate it into another
language), so the result can be passed to a printf style function (with the remaining arguments to the format function the same as they would have been for
the unmodified string). For example, the declaration
extern char *
my_dgettext (char *my_domain, const char *my_format)
__attribute__ ((format_arg (2)));
causes the compiler to check the arguments in calls to a printf type function, whose format string argument is the result of a call to the my_dgettext function,
for consistency with the format string argument my_format. If the format_arg attribute had not been specified, all the compiler could tell in such calls to
format functions would be that the format string argument is not constant; this would generate a warning when '-Wformat-nonliteral' is used, but the calls
could not be checked without the attribute.
The parameter string-index specifies which argument is the format string argument (starting from 1).
The format-arg attribute allows you to identify your own functions which modify format strings, so that GCC can check the calls to printf type functions whose
operands are calls to one of your own functions. (The compiler always treats gettext, dgettext, and dcgettext in this manner except when strict ISO C
support is requested by '-ansi' or an appropriate '-std' option, or '-ffreestanding' is used. See Options Controlling C Dialect.)
no_instrument_function
If '-finstrument-functions' is given, profiling function calls will be generated at entry and exit of most user-compiled functions. Functions with this attribute
will not be so instrumented.
section
Normally, the compiler places all code and data it generates in the .data section. Sometimes, however, you need additional sections, or you need certain
particular functions to appear in special sections. The section attribute specifies that a function lives in a particular section. For example, the declaration:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 34 of 173
The use of this attribute is limited in TIGCC, because its linker supports only a few types of sections.
constructor, destructor
The constructor attribute causes the function to be called automatically before execution enters _main. Similarly, the destructor attribute causes the
function to be called automatically after _main has completed or exit has been called. Functions with these attributes are useful for initializing data that will be
used implicitly during the execution of the program.
unused
This attribute, attached to a function, means that the function is meant to be possibly unused. GCC will not produce a warning for this function.
The unused attribute can also be used for variables and types.
used
This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for
example, when the function is referenced only in inline assembly.
malloc
The malloc attribute is used to tell the compiler that a function may be treated as if it were the malloc function. The compiler assumes that calls to malloc
result in a pointers that cannot alias anything. This will often improve optimization.
alias
The alias attribute causes the declaration to be emitted as an alias for another symbol, which must be specified. For instance,
Not all target machines support this attribute. We haven't tested yet whether it is supported for the Motorola 68000.
always_inline
Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the function even if no optimization level
was specified.
noinline
This function attribute prevents a function from being considered for inlining.
deprecated
The deprecated attribute results in a warning if the function is used anywhere in the source file. This is useful when identifying functions that are expected to
be removed in a future version of a program. The warning also includes the location of the declaration of the deprecated function, to enable users to easily find
further information about why the function is deprecated, or what they should do instead. Note that the warnings only occurs for uses:
The deprecated attribute can also be used for variables and types.
regparm, stkparm
The regparm attribute causes the function to use regcount data registers and regcount address registers for parameters. stkparm means the exact opposite, i.e.
all parameters are passed on the stack. The '-mregparm' switch specifies which one is the default, and the default for regcount.
nonnull
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 35 of 173
The nonnull attribute specifies that some function parameters should be non-null pointers. For instance, the declaration:
extern void *
my_memcpy (void *dest, const void *src, size_t len)
__attribute__((nonnull (1, 2)));
causes the compiler to check that, in calls to my_memcpy, arguments dest and src are non-null. If the compiler determines that a null pointer is passed in an
argument slot marked as non-null, and the '-Wnonnull' option is enabled, a warning is issued. The compiler may also choose to make optimizations based on
the knowledge that certain function arguments will not be null.
If no argument index list is given to the nonnull attribute, all pointer arguments are marked as non-null. To illustrate, the following declaration is equivalent to
the previous example:
extern void *
my_memcpy (void *dest, const void *src, size_t len)
__attribute__((nonnull));
nothrow
The nothrow attribute is used to inform the compiler that a function cannot throw an exception. This is probably useless in TIGCC, as it implements its own
error-handling mechanism.
The keyword __attribute__ allows you to specify special attributes of variables or structure fields. This keyword is followed by an attribute specification inside
double parentheses. The following attributes are currently defined for variables:
aligned
mode
nocommon
packed
section
transparent_union
cleanup
unused
deprecated
Other attributes are available for functions (see Function Attributes) and for types (see Type Attributes).
You may also specify attributes with __ preceding and following each keyword. This allows you to use them in header files without being concerned about a
possible macro of the same name. For example, you may use __aligned__ instead of aligned.
See Attribute Syntax for details of the exact syntax for using attributes.
To specify multiple attributes, separate them by commas within the double parentheses: for example, __attribute__ ((aligned (16), packed)).
aligned
This attribute specifies a minimum alignment for the variable or structure field, measured in bytes. For example, the declaration:
You can also specify the alignment of structure fields. For example, to create a 4-byte aligned int pair, you could write:
As in the preceding examples, you can explicitly specify the alignment (in bytes) that you wish the compiler to use for a given variable or structure field.
Alternatively, you can leave out the alignment factor and just ask the compiler to align a variable or field to the maximum useful alignment for the target
machine you are compiling for. For example, you could write:
Whenever you leave out the alignment factor in an aligned attribute specification, the compiler automatically sets the alignment for the declared variable or
field to the largest alignment which is ever used for any data type on the target machine you are compiling for (useless in TIGCC, since everything is already
aligned well enough with the default 2-byte alignment).
The aligned attribute can only increase the alignment; but you can decrease it by specifying packed as well.
mode
This attribute specifies the data type for the declaration - whichever type corresponds to the mode mode. This in effect lets you request an integer or floating
point type according to its width.
You may also specify a mode of byte or __byte__ to indicate the mode corresponding to a one-byte integer, word or __word__ for the mode of a one-word
integer, and pointer or __pointer__ for the mode used to represent pointers.
nocommon
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 36 of 173
This attribute requests GCC not to place a variable "common" but instead to allocate space for it directly. If you specify the '-fno-common' flag, GCC will do
this for all variables.
Specifying the nocommon attribute for a variable provides an initialization of zeros. A variable may only be initialized in one source file.
packed
The packed attribute specifies that a variable or structure field should have the smallest possible alignment - one byte for a variable, and one bit for a field,
unless you specify a larger value with the aligned attribute.
struct foo
{
char a;
int x[2] __attribute__ ((packed));
};
section
Normally, the compiler places the objects it generates in sections like .data and .bss. Sometimes, however, you need additional sections, or you need certain
particular variables to appear in special sections, for example to map to special hardware. The section attribute specifies that a variable (or function) lives in a
particular section. The use of this attribute is limited in TIGCC, because its linker supports only a few types of sections, but this may be improved in the future.
For example, this small hypothetical program uses several specific section names:
main()
{
/* Initialize stack pointer */
init_sp (stack + sizeof (stack));
Use the section attribute with an initialized definition of a global variable, as shown in the example. GCC issues a warning and otherwise ignores the section
attribute in uninitialized variable declarations.
You may only use the section attribute with a fully initialized global definition because of the way linkers work. The linker requires each object be defined once,
with the exception that uninitialized variables tentatively go in the .bss section and can be multiply "defined". You can force a variable to be initialized with the
'-fno-common' flag or the nocommon attribute.
transparent_union
This attribute, attached to a function parameter which is a union, means that the corresponding argument may have the type of any union member, but the
argument is passed as if its type were that of the first union member. For more details, see the transparent_union type attribute. You can also use this
attribute on a typedef for a union data type; then it applies to all function parameters with that type.
cleanup
The cleanup attribute runs a function when the variable goes out of scope. This attribute can only be applied to auto function scope variables; it may not be
applied to parameters or variables with static storage duration. The function must take one parameter, a pointer to a type compatible with the variable. The
return value of the function (if any) is ignored.
If '-fexceptions' is enabled, then cleanup_function will be run during the stack unwinding that happens during the processing of the exception. Note that the
cleanup attribute does not allow the exception to be caught, only to perform an action. Note that TIGCC defines its own error handling mechanism, so this
attribute will not work if used in this way. It is undefined what happens if cleanup_function does not return normally.
unused
This attribute, attached to a variable, means that the variable is meant to be possibly unused. GCC will not produce a warning for this variable.
The unused attribute can also be used for functions and types.
deprecated
The deprecated attribute results in a warning if the variable is used anywhere in the source file. This is useful when identifying variables that are expected to
be removed in a future version of a program. The warning also includes the location of the declaration of the deprecated variable, to enable users to easily find
further information about why the variable is deprecated, or what they should do instead. Note that the warnings only occurs for uses:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 37 of 173
The deprecated attribute can also be used for functions and types.
The keyword __attribute__ allows you to specify special attributes of struct and union types when you define such types. This keyword is followed by an
attribute specification inside double parentheses. The following attributes are currently defined for types:
aligned
packed
transparent_union
may_alias
unused
deprecated
Other attributes are defined for functions (see Function Attributes) and for variables (see Variable Attributes).
You may also specify any one of these attributes with __ preceding and following its keyword. This allows you to use these attributes in header files without
being concerned about a possible macro of the same name. For example, you may use __aligned__ instead of aligned.
You may specify the aligned and transparent_union attributes either in a typedef declaration or just past the closing curly brace of a complete enum, struct
or union type definition and the packed attribute only past the closing brace of a definition.
You may also specify attributes between the enum, struct or union tag and the name of the type rather than after the closing brace.
See Attribute Syntax for details of the exact syntax for using attributes.
To specify multiple attributes, separate them by commas within the double parentheses: for example, __attribute__ ((aligned (16), packed)).
aligned
This attribute specifies a minimum alignment (in bytes) for variables of the specified type. For example, the declarations:
force the compiler to insure (as far as it can) that each variable whose type is struct S or more_aligned_int will be allocated and aligned at least on a 8-byte
boundary.
Note that the alignment of any given struct or union type is required by the ISO C standard to be at least a perfect multiple of the lowest common multiple of
the alignments of all of the members of the struct or union in question. This means that you can effectively adjust the alignment of a struct or union type by
attaching an aligned attribute to any one of the members of such a type, but the notation illustrated in the example above is a more obvious, intuitive, and
readable way to request the compiler to adjust the alignment of an entire struct or union type.
As in the preceding example, you can explicitly specify the alignment (in bytes) that you wish the compiler to use for a given struct or union type.
Alternatively, you can leave out the alignment factor and just ask the compiler to align a type to the maximum useful alignment for the target machine you are
compiling for. For example, you could write:
Whenever you leave out the alignment factor in an aligned attribute specification, the compiler automatically sets the alignment for the type to the largest
alignment which is ever used for any data type on the target machine you are compiling for (useless in TIGCC, since everything is already aligned well enough
with the default 2-byte alignment).
The aligned attribute can only increase the alignment; but you can decrease it by specifying packed as well.
packed
This attribute, attached to an enum, struct, or union type definition, specified that the minimum required memory be used to represent the type.
Specifying this attribute for struct and union types is equivalent to specifying the packed attribute on each of the structure or union members. Specifying the
'-fshort-enums' flag on the line is equivalent to specifying the packed attribute on all enum definitions.
You may only specify this attribute after a closing curly brace on an enum definition, not in a typedef declaration, unless that declaration also contains the
definition of the enum.
transparent_union
This attribute, attached to a union type definition, indicates that any function parameter having that union type causes calls to that function to be treated in a
special way.
First, the argument corresponding to a transparent union type can be of any type in the union; no cast is required. Also, if the union contains a pointer type,
the corresponding argument can be a null pointer constant or a void pointer expression; and if the union contains a void pointer type, the corresponding
argument can be any pointer expression. If the union member type is a pointer, qualifiers like const on the referenced type must be respected, just as with
normal pointer conversions.
Second, the argument is passed to the function using the calling conventions of first member of the transparent union, not the calling conventions of the union
itself. All members of the union must have the same machine representation; this is necessary for this argument passing to work properly.
Transparent unions are designed for library functions that have multiple interfaces for compatibility reasons, but they may be used for various different
purposes.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 38 of 173
may_alias
Accesses to objects with types with this attribute are not subjected to type-based alias analysis, but are instead assumed to be able to alias any other type of
objects, just like the char type. See '-fstrict-aliasing' for more information on aliasing issues.
Example of use:
b[1] = 0;
if (a == 0x12345678)
abort();
/* ... */
}
If you replaced short_a with short in the variable declaration, the above program would abort when compiled with '-fstrict-aliasing', which is on by default
at '-O2' or above in recent GCC versions.
unused
When attached to a type (including a union or a struct), this attribute means that variables of that type are meant to appear possibly unused. GCC will not
produce a warning for any variables of that type, even if the variable appears to do nothing.
The unused attribute can also be used for functions and variables.
deprecated
The deprecated attribute results in a warning if the type is used anywhere in the source file. This is useful when identifying types that are expected to be
removed in a future version of a program. If possible, the warning also includes the location of the declaration of the deprecated type, to enable users to easily
find further information about why the type is deprecated, or what they should do instead. Note that the warnings only occur for uses and then only if the type
is being applied to an identifier that itself is not being declared as deprecated.
results in a warning on line 2 and 3 but not lines 4, 5, or 6. No warning is issued for line 4 because T2 is not explicitly deprecated. Line 5 has no warning
because T3 is explicitly deprecated. Similarly for line 6.
The deprecated attribute can also be used for functions and variables.
Attribute Syntax
This section describes the syntax with which __attribute__ may be used, and the constructs to which attribute specifiers bind, for the C language. Because of
infelicities in the grammar for attributes, some forms described here may not be successfully parsed in all cases.
See Function Attributes for details of the semantics of attributes applying to functions. See Variable Attributes for details of the semantics of attributes applying
to variables. See Type Attributes for details of the semantics of attributes applying to structure, union and enumerated types.
An attribute specifier is of the form __attribute__ ((attribute-list)). An attribute list is a possibly empty comma-separated sequence of attributes, where
each attribute is one of the following:
A word (which may be an identifier such as unused, or a reserved word such as const).
A word, followed by, in parentheses, parameters for the attribute. These parameters take one of the following forms:
An identifier. For example, mode attributes use this form.
An identifier followed by a comma and a non-empty comma-separated list of expressions. For example, format attributes use this form.
A possibly empty comma-separated list of expressions. For example, format_arg attributes use this form with the list being a single integer
constant expression, and alias attributes use this form with the list being a single string constant.
An attribute specifier list is a sequence of one or more attribute specifiers, not separated by any other tokens.
An attribute specifier list may appear after the colon following a label, other than a case or default label. The only attribute it makes sense to use after a label
is unused. This feature is intended for code generated by programs which contains labels that may be unused but which is compiled with '-Wall'. It would not
normally be appropriate to use in it human-written code, though it could be useful in cases where the code that jumps to the label is contained within an
#ifdef conditional.
An attribute specifier list may appear as part of a struct, union or enum specifier. It may go either immediately after the struct, union or enum keyword, or
after the closing brace. It is ignored if the content of the structure, union or enumerated type is not defined in the specifier in which the attribute specifier list is
used - that is, in usages such as struct __attribute__((foo)) bar with no following opening brace. Where attribute specifiers follow the closing brace, they
are considered to relate to the structure, union or enumerated type defined, not to any enclosing declaration the type specifier appears in, and the type defined
is not complete until after the attribute specifiers.
Otherwise, an attribute specifier appears as part of a declaration, counting declarations of unnamed parameters and type names, and relates to that declaration
(which may be nested in another declaration, for example in the case of a parameter declaration), or to a particular declarator within a declaration. Where an
attribute specifier is applied to a parameter declared as a function or an array, it should apply to the function or array rather than the pointer to which the
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 39 of 173
Any list of specifiers and qualifiers at the start of a declaration may contain attribute specifiers, whether or not such a list may in that context contain storage
class specifiers. (Some attributes, however, are essentially in the nature of storage class specifiers, and only make sense where storage class specifiers may be
used; for example, section.) There is one necessary limitation to this syntax: the first old-style parameter declaration in a function definition cannot begin with
an attribute specifier, because such an attribute applies to the function instead by syntax described below (which, however, is not yet implemented in this
case). In some other cases, attribute specifiers are permitted by this grammar but not yet supported by the compiler. All attribute specifiers in this place relate
to the declaration as a whole. In the obsolescent usage where a type of int is implied by the absence of type specifiers, such a list of specifiers and qualifiers
may be an attribute specifier list with no other specifiers or qualifiers.
An attribute specifier list may appear immediately before a declarator (other than the first) in a comma-separated list of declarators in a declaration of more
than one identifier using a single list of specifiers and qualifiers. Such attribute specifiers apply only to the identifier before whose declarator they appear. For
example, in
the noreturn attribute applies to all the functions declared; the format attribute only applies to d1.
An attribute specifier list may appear immediately before the comma, = or semicolon terminating the declaration of an identifier other than a function definition.
At present, such attribute specifiers apply to the declared object or function, but in future they may attach to the outermost adjacent declarator. In simple
cases there is no difference, but, for example, in
at present the noreturn attribute applies to f, which causes a warning since f is not a function, but in future it may apply to the function ****f. The precise
semantics of what attributes in such cases will apply to are not yet specified. Where an assembler name for an object or function is specified (see Asm Labels),
at present the attribute must follow the asm specification; in future, attributes before the asm specification may apply to the adjacent declarator, and those after
it to the declared object or function.
An attribute specifier list may, in future, be permitted to appear after the declarator in a function definition (before any old-style parameter declarations or the
function body).
Attribute specifiers may be mixed with type qualifiers appearing inside the [] of a parameter array declarator, in the C99 construct by which such qualifiers are
applied to the pointer to which the array is implicitly converted. Such attribute specifiers apply to the pointer, not to the array, but at present this is not
implemented and they are ignored.
An attribute specifier list may appear at the start of a nested declarator. At present, there are some limitations in this usage: the attributes correctly apply to
the declarator, but for most individual attributes the semantics this implies are not implemented. When attribute specifiers follow the * of a pointer declarator,
they may be mixed with any type qualifiers present. The following describes the formal semantics of this syntax. It will make the most sense if you are familiar
with the formal specification of declarators in the ISO C standard.
Consider (as in C99 subclause 6.7.5 paragraph 4) a declaration T D1, where T contains declaration specifiers that specify a type Type (such as int) and D1 is a
declarator that contains an identifier ident. The type specified for ident for derived declarators whose type does not include an attribute specifier is as in the ISO
C standard.
If D1 has the form ( attribute-specifier-list D ), and the declaration T D specifies the type "derived-declarator-type-list Type" for ident, then T D1
specifies the type "derived-declarator-type-list attribute-specifier-list Type" for ident.
If D1 has the form * type-qualifier-and-attribute-specifier-list D, and the declaration T D specifies the type "derived-declarator-type-list Type" for
ident, then T D1 specifies the type "derived-declarator-type-list type-qualifier-and-attribute-specifier-list Type" for ident.
For example,
specifies the type "pointer to pointer to pointer to pointer to non-returning function returning void". As another example,
specifies the type "pointer to 8-byte-aligned pointer to char". Note again that this does not work with most attributes; for example, the usage of aligned and
noreturn attributes given above is not yet supported.
For compatibility with existing code written for compiler versions that did not implement attributes on nested declarators, some laxity is allowed in the placing
of attributes. If an attribute that only applies to types is applied to a declaration, it will be treated as applying to the type of that declaration. If an attribute that
only applies to declarations is applied to the type of a declaration, it will be treated as applying to that declaration; and, for compatibility with code placing the
attributes immediately before the identifier declared, such an attribute applied to a function return type will be treated as applying to the function type, and
such an attribute applied to an array element type will be treated as applying to the array type. If an attribute that only applies to function types is applied to a
pointer-to-function type, it will be treated as applying to the pointer target type; if such an attribute is applied to a function return type that is not a pointer-to-
function type, it will be treated as applying to the function type.
GNU C extends ISO C to allow a function prototype to override a later old-style non-prototype definition. Consider the following example:
Suppose the type uid_t happens to be char. ISO C does not allow this example, because subword arguments in old-style non-prototype definitions are
promoted. Therefore in this example the function definition's argument is really an int, which does not match the prototype argument type of char.
This restriction of ISO C makes it hard to write code that is portable to traditional C compilers, because the programmer does not know whether the uid_t type
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 40 of 173
is short, int, or long. Therefore, in cases like these GNU C allows a prototype to override a later old-style definition. More precisely, in GNU C, a function
prototype argument type overrides the argument type specified by a later old-style definition if the former type is the same as the latter type before promotion.
Thus in GNU C the above example is equivalent to the following:
int
isroot (uid_t x)
{
return x == 0;
}
In GNU C, you may use C++ style comments, which start with // and continue until the end of the line. Many other C implementations allow such comments,
and they are included in the 1999 C standard. However, C++ style comments are not recognized if you specify an '-std' option specifying a version of ISO C
before C99, or '-ansi' (equivalent to '-std=c89').
In GNU C, you may normally use dollar signs in identifier names. This is because many traditional C implementations allow such identifiers.
You can use the sequence \e in a string or character constant to stand for the ASCII character ESC (\x1B).
The keyword __alignof__ allows you to inquire about how an object is aligned, or the minimum alignment usually required by a type. Its syntax is just like
sizeof.
If the operand of __alignof__ is an lvalue rather than a type, its value is the required alignment for its type, taking into account any minimum alignment
specified with GCC's aligned attribute. For example, after this declaration:
the value of __alignof__ (foo1.y) is 1, even though its actual alignment is 2, the same as __alignof__ (int).
Inline Functions
By declaring a function inline, you can direct GCC to integrate that function's code into the code for its callers. This makes execution faster by eliminating the
function-call overhead; in addition, if any of the actual argument values are constant, their known values may permit simplifications at compile time so that not
all of the inline function's code needs to be included. The effect on code size is less predictable; object code may be larger or smaller with function inlining,
depending on the particular case. Inlining of functions is an optimization and it really "works" only in optimizing compilation. If you don't use '-O', no function is
really inline.
Inline functions are included in the ISO C99 standard, but there are currently substantial differences between what GCC implements and what the ISO C99
standard requires.
To declare a function inline, use the inline keyword in its declaration, like this:
inline int
inc (int *a)
{
(*a)++;
}
(If you are writing a header file to be included in ISO C programs, write __inline__ instead of inline. See Alternate Keywords.) You can also make all "simple
enough" functions inline with the option '-finline-functions'.
Note that certain usages in a function definition can make it unsuitable for inline substitution. Among these usages are: use of a variable number of arguments,
use of alloca, use of variable sized data types (see Variable Length Arrays), use of computed goto (see Labels as Values), use of nonlocal goto, and nested
functions (see Nested Functions). Using '-Winline' will warn when a function marked inline could not be substituted, and will give the reason for the failure.
Note that in C (unlike C++), the inline keyword does not affect the linkage of the function.
When a function is both inline and static, if all calls to the function are integrated into the caller, and the function's address is never used, then the function's
own assembler code is never referenced. In this case, GCC does not actually output assembler code for the function, unless you specify the option '-fkeep-
inline-functions'. Some calls cannot be integrated for various reasons (in particular, calls that precede the function's definition cannot be integrated, and
neither can recursive calls within the definition). If there is a nonintegrated call, then the function is compiled to assembler code as usual. The function must
also be compiled as usual if the program refers to its address, because that can't be inlined.
When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only
once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline
function is always compiled on its own in the usual fashion.
If you specify both inline and extern in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not
even if you refer to its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it.
This combination of inline and extern has almost the effect of a macro. The way to use it is to put a function definition in a header file with these keywords,
and put another copy of the definition (lacking inline and extern) in a library file. The definition in the header file will cause most calls to the function to be
inlined. If any uses of the function remain, they will refer to the single copy in the library.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 41 of 173
For future compatibility with when GCC implements ISO C99 semantics for inline functions, it is best to use static inline only. (The existing semantics will
remain available when '-std=gnu89' is specified, but eventually the default will be '-std=gnu99' and that will implement the C99 semantics, though it does
not do so yet.)
GCC does not inline any functions when not optimizing unless you specify the always_inline attribute for the function, like this:
/* Prototype. */
inline void foo (const char*) __attribute__((always_inline));
Inline Assembler
GCC introduces a special asm keyword to support assembler instructions within C code. Roughly, its syntax is:
The asm keyword may appear between usual lines of code or at the top level, outside of any function body. instructions may contain labels and references to
global C symbols; in fact, the contents of the string are copied directly into the output file.
If you are writing a header file that should be includable in programs compiled in GCC's strict ISO C mode, write __asm__ instead of asm. See Alternate
Keywords.
asm ("instructions");
where instructions contains one or more assembler instructions separated by semicolons or newlines.
In TIGCC, all register names must be preceded by a percent sign, to avoid confusion with C variables named like one of the CPU registers. For example:
Hexadecimal constants must be written according to C syntax (like 0xC8), not using the notation $C8 which is common in various assemblers.
will be interpreted quite differently: a0 will be regarded as a C language variable, not a register! Read the documentation about the GNU Assembler for more
information about the exact syntax and directives which it accepts; since inline assembler instructions are copied directly into the output of the compiler,
exactly the same features are available.
Newlines as separators are also accepted in instructions, so the following code is valid as well:
In an assembler instruction using asm, you can specify the operands of the instruction using C expressions. This means you need not guess which registers or
memory locations will contain the data you want to use.
You must specify an assembler instruction template much like what appears in a machine description, plus an operand constraint string for each operand.
For the beginning, you will be given here a very illustrative example on how to use the 68881's fsinx instruction (note that this example is not applicable to TI
calculators, because the MC68000 processor which is built into the TI-89 and TI-92+ does not have this instruction, but the example is illustrative anyway):
Here angle is the C expression for the input operand while result is that of the output operand. Each has "f" as its operand constraint, saying that a floating
point register is required. The = in =f indicates that the operand is an output; all output operands' constraints must use =. The constraints use the same
language used in the machine description (see the section Operand Constraints). In this example, the compiler will convert this instruction into a sequence of
assembly instructions which will ensure that the evaluated expression angle is really stored in one of the 68881's floating point registers, and which will store
the result of the fsinx (which is in some other floating point register) into the expression result (note that result need not be a variable; it can be any lvalue
expression, for example a dereferenced pointer).
Each operand is described by an operand-constraint string followed by the C expression in parentheses. A colon separates the assembler template from the first
output operand and another separates the last output operand from the first input, if any. Commas separate the operands within each group. The total number
of operands is currently limited to 30; this limitation may be lifted in some future version of GCC.
If there are no output operands but there are input operands, you must place two consecutive colons surrounding the place where the output operands would
go.
As of GCC version 3.1, it is also possible to specify input and output operands using symbolic names which can be referenced within the assembler code. These
names are specified inside square brackets preceding the constraint string, and can be referenced inside the assembler code using %[name] instead of a
percentage sign followed by the operand number. Using named operands the above example could look like:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 42 of 173
Note that the symbolic operand names have no relation whatsoever to other C identifiers. You may use any name you like, even those of existing C symbols,
but must ensure that no two operands within the same assembler construct use the same symbolic name.
Output operand expressions must be lvalues; the compiler can check this. The input operands need not be lvalues. The compiler cannot check whether the
operands have data types that are reasonable for the instruction being executed. It does not parse the assembler instruction template and does not know what
it means or even whether it is valid assembler input. The extended asm feature is most often used for machine instructions the compiler itself does not know
exist. If the output expression cannot be directly addressed (for example, it is a bit-field), your constraint must allow a register. In that case, GCC will use the
register as the output of the asm, and then store that register into the output.
Here is an another example, which is applicable to TIGCC. Suppose that we want to rotate the value of the expression input one bit to the left, and to store the
result into the expression output (which is an lvalue). We can write the following code:
asm ("move.l %1,%%d0; rol #1,%%d0; move.l %%d0,%0" : "=g" (output) : "g" (input));
Note that when extended asm constructions are used, the percent sign before the register names must be doubled. It is important to say that in the above
example input and output may be any valid expressions; in the simple case when both of them are just global variables, a simple asm construction like
would be quite enough. Extended asm constructions allow encapsulating them in macros which look like functions, like in the following example, which defines a
macro 'rotate' which acts like a void function:
The ordinary output operands must be write-only; GCC will assume that the values in these operands before the instruction are dead and need not be
generated. That's why the following version of 'rotate' macro which accepts just one argument (and which rotates it one bit to the left) is quite unreliable:
To solve such difficulties, extended asm supports input-output or read-write operands. Use the constraint character + to indicate such an operand and list it with
the output operands.
When the constraints for the read-write operand (or the operand in which only some of the bits are to be changed) allows a register, you may, as an
alternative, logically split its function into two separate operands, one input operand and one write-only output operand. The connection between them is
expressed by constraints which say they need to be in the same location when the instruction executes. You can use the same C expression for both operands,
or different expressions. For example, here we write the (fictitious) combine instruction with bar as its read-only source operand and foo as its read-write
destination:
The constraint "0" for operand 1 says that it must occupy the same location as operand 0. A number in constraint is allowed only in an input operand and it
must refer to an output operand.
Only a number in the constraint can guarantee that one operand will be in the same place as another. The mere fact that foo is the value of both operands is
not enough to guarantee that they will be in the same place in the generated assembler code. The following would not work reliably:
Various optimizations or reloading could cause operands 0 and 1 to be in different registers; GCC knows no reason not to do so. For example, the compiler
might find a copy of the value of foo in one register and use it for operand 1, but generate the output operand 0 in a different register (copying it afterward to
foo's own address). Of course, since the register for operand 1 is not even mentioned in the assembler code, the result will not work, but GCC can't tell that.
As of GCC version 3.1, one may write [name] instead of the operand number for a matching constraint. For example:
All the examples given above have a serious drawback: they clobber the register 'd0'. If the compiler keeps something important in it (which is very likely),
this may cause lots of trouble. Of course, you can save it on the stack at the beginning and restore it at the end, but there is a much better solution which will
save clobbered registers only when necessary. To describe clobbered registers, write a third colon after the input operands, followed by the names of the
clobbered registers (given as strings), separated by commas:
You may not write a clobber description in a way that overlaps with an input or output operand. For example, you may not have an operand describing a
register class with one member if you mention that register in the clobber list. Variables declared to live in specific registers (see Explicit Reg Vars), and used as
asm input or output operands must have no part mentioned in the clobber description. There is no way for you to specify that an input operand is modified
without also specifying it as an output operand. Note that if all the output operands you specify are for this purpose (and hence unused), you will then also
need to specify volatile for the asm construct, as described below, to prevent GCC from deleting the asm statement as unused.
Whenever you refer to a particular hardware register from the assembler code, you will probably have to list the register after the third colon to tell the
compiler the register's value is modified. Alternatively, you can force the compiler to use any data register instead of 'd0', using the following trick:
Here, the "d" constraint ensures that '__temp' will be stored in the data register (note that rol is applicable only to data registers). In fact, there is no need
for a temporary register if we forced the output to be in a data register, which can be implemented as in the following example:
If your assembler instruction can alter the condition code register, add cc to the list of clobbered registers. GCC on some machines represents the condition
codes as a specific hardware register; cc serves to name this register. On other machines, the condition code is handled differently, and specifying cc has no
effect. But it is valid no matter what the machine.
If your assembler instruction modifies memory in an unpredictable fashion, add memory to the list of clobbered registers. This will cause GCC to not keep
memory values cached in registers across the assembler instruction. You will also want to add the volatile keyword if the memory affected is not listed in the
inputs or outputs of the asm, as the memory clobber does not count as a side-effect of the asm.
As already mentioned above, you can put multiple assembler instructions together in a single asm template, separated either with newlines or with semicolons
(the GNU assembler allows semicolons as a line-breaking character). The input operands are guaranteed not to use any of the clobbered registers, and neither
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 43 of 173
will the output operands' addresses, so you can read and write the clobbered registers as many times as you like. Here is an example of multiple instructions in
a template; it assumes the subroutine _foo accepts arguments in registers a0 and a1:
Unless an output operand has the '&' constraint modifier, GCC may allocate it in the same register as an unrelated input operand, on the assumption the
inputs are consumed before the outputs are produced. This assumption may be false if the assembler code actually consists of more than one instruction. In
such a case, use '&' for each output operand that may not overlap an input. See the section Constraint Modifier Characters.
If you want to test the condition code produced by an assembler instruction, you must include a branch and a label in the asm construct, as follows:
asm ("clr.l %0; test.l %1; beq 0f; moveq #1,%0; 0:"
: "g" (result) : "g" (input));
This assumes your assembler supports local labels, which is true for the GNU Assembler (it uses the suffix 'f' for forward and 'b' for backward local labels;
see the section about Local Symbol Names).
Speaking of labels, jumps from one asm to another are not supported. The compiler's optimizers do not know about these jumps, and therefore they cannot
take account of them when deciding how to optimize.
As already mentioned, usually the most convenient way to use these asm instructions is to encapsulate them in macros that look like functions. Here is an
example of how to define a function-looking macro with a non-void return type:
#define rotate(x) \
({ unsigned long __result, __arg=(x); \
asm ("move.l %1,%0; rol #1,%0": "=d" (__result): "g" (__arg)); \
__result; })
This macro acts nearly exactly like a function which takes one unsigned long argument, and which returns an unsigned long result. Here the variable __arg
is used to make sure that the instruction operates on a proper unsigned long value, and to accept only those arguments x which can convert automatically to
an unsigned long.
Another way to make sure the instruction operates on the correct data type is to use a cast in the asm. This is different from using a variable __arg in that it
converts more different types. For example, if the desired type were int, casting the argument to int would accept a pointer with no complaint, while assigning
the argument to an int variable named __arg would warn about using a pointer unless the caller explicitly casts it.
If an asm has output operands, GCC assumes for optimization purposes the instruction has no side effects except to change the output operands. This does not
mean instructions with a side effect cannot be used, but you must be careful, because the compiler may eliminate them if the output operands aren't used, or
move them out of loops, or replace two with one if they constitute a common subexpression. Also, if your instruction does have a side effect on a variable that
otherwise appears not to change, the old value of the variable may be reused later if it happens to be found in a register.
If you are not happy with this behavior, you can prevent an asm instruction from being deleted, moved significantly, or combined, by writing the keyword
volatile after the asm. For example:
#define get_and_set_priority(new) \
({ int __old; \
asm volatile ("get_and_set_priority %0, %1" \
: "=g" (__old) : "g" (new)); \
__old; })
If you write an asm instruction with no outputs, GCC will know the instruction has side-effects and will not delete the instruction or move it outside of loops.
The volatile keyword indicates that the instruction has important side-effects. GCC will not delete a volatile asm if it is reachable. (The instruction can still be
deleted if GCC can prove that control-flow will never reach the location of the instruction.) In addition, GCC will not reschedule instructions across a volatile asm
instruction. For example:
#define inline_rowread(x) \
({*(short*)0x600018=(short)(x); \
asm volatile("nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop":::"memory"); \
~(*(unsigned char*)0x60001b);})
Here, we can read the keyboard port at 0x60001b only 12 nops after setting the keyboard mask at 0x600018. Therefore, we need to make sure that the nops
get scheduled between the write to 0x600018 and the read to 0x60001b. The volatile keyword makes sure that the instructions get ordered in the correct
way.
Note that even a volatile asm instruction can be moved in ways that appear insignificant to the compiler, such as across jump instructions. You can't expect a
sequence of volatile asm instructions to remain perfectly consecutive. If you want consecutive output, use a single asm. Also, GCC will perform some
optimizations across a volatile asm instruction; GCC does not "forget everything" when it encounters a volatile asm instruction the way some other compilers do.
An asm instruction without any operands or clobbers (an "old style" asm) will be treated identically to a volatile asm instruction.
It is a natural idea to look for a way to give access to the condition code left by the assembler instruction. However, when we attempted to implement this, we
found no way to make it work reliably. The problem is that output operands might need reloading, which would result in additional following "store" instructions.
On most machines, these instructions would alter the condition code before there was time to test it. This problem doesn't arise for ordinary "test" and
"compare" instructions because they don't have any output operands.
For reasons similar to those described above, it is not possible to give an assembler instruction access to the condition code left by previous instructions.
You can write write __asm__ instead of asm. See section Alternate Keywords.
Operand Constraints
Each match operand in an instruction pattern can specify a constraint for the type of operands allowed. Constraints can say whether an operand may be in a
register, and which kinds of register; whether the operand can be a memory reference, and which kinds of address; whether the operand may be an immediate
constant, and which possible values it may have. Constraints can also require two operands to match. Here, only those operand constraints which are valid for
the Motorola 68000 processor and the built-in inline assembly will be described (i.e. those which are applicable to TIGCC).
Simple Constraints
Constraint Modifier Characters
Simple Constraints
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 44 of 173
The simplest kind of constraint is a string full of letters, each of which describes one kind of operand that is permitted. These are the letters that are allowed:
m
A memory operand is allowed, with any kind of address that the machine supports in general.
o
A memory operand is allowed, but only if the address is offsettable. This means that adding a small integer (actually, the width in bytes of the operand,
as determined by its machine mode) may be added to the address and the result is also a valid memory address. For example, an address which is
constant is offsettable; so is an address that is the sum of a register and a constant (as long as a slightly larger constant is also within the range of
address-offsets supported by the machine); but an autoincrement or autodecrement address is not offsettable. More complicated indirect/indexed
addresses may or may not be offsettable depending on the other addressing modes that the machine supports.
Note that in an output operand which can be matched by another operand, the constraint letter o is valid only when accompanied by both < (if the target
machine has predecrement addressing) and > (if the target machine has preincrement addressing).
V
A memory operand that is not offsettable. In other words, anything that would fit the m constraint but not the o constraint.
<
A memory operand with autodecrement addressing is allowed.
>
A memory operand with autoincrement addressing is allowed.
r
A register operand is allowed provided that it is in a general register.
d
A data register is allowed. This is a Motorola-specific constraint.
a
An address register is allowed. This is a Motorola-specific constraint.
f
A 68881 floating-point register is allowed, if available (of course, it is not available on the TI-89 and TI-92 Plus). This is a Motorola-specific constraint.
i
An immediate integer operand (one with constant value) is allowed. This includes symbolic constants whose values will be known only at assembly time.
n
An immediate integer operand with a known numeric value is allowed. Many systems cannot support assembly-time constants for operands less than a
word wide. Constraints for these operands should use n rather than i.
I
An integer in the range 1 to 8 is allowed. This is a Motorola-specific constraint, and this is for example the range permitted as a shift count in the shift
instructions.
J
A 16 bit signed number is allowed. This is a Motorola-specific constraint.
K
A signed number whose magnitude is greater than 0x80 is allowed. This is a Motorola-specific constraint.
L
An integer in the range -8 to -1 is allowed. This is a Motorola-specific constraint.
M
A signed number whose magnitude is greater than 0x100 is allowed. This is a Motorola-specific constraint.
s
An immediate integer operand whose value is not an explicit integer is allowed.
This might appear strange; if an instruction allows a constant operand with a value not known at compile time, it certainly must allow any known value.
So why use s instead of i? Sometimes it allows better code to be generated. For example, on the 68000 in a fullword instruction it is possible to use an
immediate operand; but if the immediate value is between -128 and 127, better code results from loading the value into a register and using the register.
This is because the load into the register can be done with a 'moveq' instruction. The GNU team arranges for this to happen by defining the letter K to
mean "any integer outside the range -128 to 127", and then specifying Ks in the operand constraints. (This constraint is very unlikely to be useful for
inline assembly, since you cannot use constraints to make GCC choose between 2 different inline assembly statements.)
g
Any register, memory or immediate integer operand is allowed, except for registers that are not general registers.
X
Any operand whatsoever is allowed, even if it does not satisfy general_operand. This is normally used in the constraint of a match_scratch when certain
alternatives will not actually require a scratch register.
0, 1, 2, ... 9
An operand that matches the specified operand number is allowed. If a digit is used together with letters within the same alternative, the digit should
come last. This is called a matching constraint and what it really means is that the assembler has only a single operand that fills two roles considered
separate. More precisely, the two operands that match must include one input-only operand and one output-only operand. Moreover, the digit must be a
smaller number than the number of the operand that uses it in the constraint.
p
An operand that is a valid memory address is allowed.
In order to have valid assembler code, each operand must satisfy its constraint. But a failure to do so does not prevent the pattern from applying to an
instruction pattern. Instead, it directs the compiler to modify the code so that the constraint will be satisfied. Usually this is done by copying an operand into a
register.
These are the constraint modifier characters which are meaningful for TIGCC:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 45 of 173
=
Means that this operand is write-only for this instruction: the previous value is discarded and replaced by output data.
+
Means that this operand is both read and written by the instruction.
When the compiler fixes up the operands to satisfy the constraints, it needs to know which operands are inputs to the instruction and which are outputs
from it. = identifies an output; + identifies an operand that is both input and output; all other operands are assumed to be input only.
If you specify = or + in a constraint, you put it in the first character of the constraint string.
&
Means (in a particular alternative) that this operand is an earlyclobber operand, which is modified before the instruction is finished using the input
operands. Therefore, this operand may not lie in a register that is used as an input operand or as part of any memory address. & does not obviate the
need to write =.
You can specify the name to be used in the assembler code for a C function or variable by writing the asm (or __asm__) keyword after the declarator as follows:
This specifies that the name to be used for the variable foo in the assembler code should be myfoo rather than the usual foo.
On systems where an underscore is normally prepended to the name of a C function or variable, this feature allows you to define names for the linker that do
not start with an underscore.
It does not make sense to use this feature with a non-static local variable since such variables do not have assembler names. If you are trying to put the
variable in a particular register, see Explicit Reg Vars. GCC presently accepts such code with a warning, but will probably be changed to issue an error, rather
than a warning, in the future.
You cannot use asm in this way in a function definition; but you can get the same effect by writing a declaration for the function before its definition and putting
asm there, like this:
It is up to you to make sure that the assembler names you choose do not conflict with any other assembler symbols. Also, you must not use a register name;
that would produce completely invalid assembler code. GCC does not as yet have the ability to store static variables in registers. Perhaps that will be added.
GNU C allows you to put a few global variables into specified hardware registers. You can also specify the register in which an ordinary register variable should
be allocated. TIGCC also allows you to specify an explicit register for function parameters.
Global register variables reserve registers throughout the program. This may be useful in programs such as programming language interpreters which
have a couple of global variables that are accessed very often.
Local register variables in specific registers do not reserve the registers. The compiler's data flow analysis is capable of determining where the specified
registers contain live values, and where they are available for other uses. Stores into local register variables may be deleted when they appear to be dead
according to dataflow analysis. References to local register variables may be deleted or moved or simplified.
In TIGCC, it is possible to specify explictly where the parameters to a function a stored, in a syntax similar to global and local register variables.
Global register variables reserve registers throughout the program. This may be useful in programs such as programming language
interpreters which have a couple of global variables that are accessed very often.
Here a3 is the name of the register which should be used. Choose a register which is normally saved and restored by function calls on your machine, so that
library routines will not clobber it.
Naturally the register name is cpu-dependent, so you would need to conditionalize your program according to cpu type. The register a3 would be a good choice
on a 68000 for a variable of pointer type. On machines with register windows, be sure to choose a "global" register that is not affected magically by the function
call mechanism.
In addition, operating systems on one type of cpu may differ in how they name the registers; then you would need additional conditionals. For example, some
68000 operating systems call this register %a3.
Eventually there may be a way of asking the compiler to choose a register automatically, but first we need to figure out how it should choose and how to enable
you to guide the choice. No solution is evident.
Defining a global register variable in a certain register reserves that register entirely for this use, at least within the current compilation. The register will not be
allocated for any other purpose in the functions in the current compilation. The register will not be saved and restored by these functions. Stores into this
register are never deleted even if they would appear to be dead, but references may be deleted or moved or simplified.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 46 of 173
It is not safe to access the global register variables from interrupt handlers, because the system library routines may temporarily use the register for other
things (unless you recompile them specially for the task at hand).
It is not safe for one function that uses a global register variable to call another such function foo by way of a third function lose that was compiled without
knowledge of this variable (i.e. in a different source file in which the variable wasn't declared). This is because lose might save the register and put some other
value there. For example, you can't expect a global register variable to be available in the comparison-function that you pass to qsort, since it might have put
something else in that register. (If you are prepared to recompile it with the same global register variable, you can solve this problem.)
If you want to recompile qsort or other source files which do not actually use your global register variable, so that they will not use that register for any other
purpose, then it suffices to specify the compiler option '-ffixed-reg'. You need not actually add a global register declaration to their source code.
A function which can alter the value of a global register variable cannot safely be called from a function compiled without this variable, because it could clobber
the value the caller expects to find there on return. Therefore, the function which is the entry point into the part of the program that uses the global register
variable must explicitly save and restore the value which belongs to its caller.
Be careful if you use longjmp with global register variables, because it will restore to each global register variable the value it had at the time of the setjmp.
All global register variable declarations must precede all function definitions. If such a declaration could appear after function definitions, the declaration would
be too late to prevent the register from being used for other purposes in the preceding functions.
Global register variables may not have initial values, because an executable file has no means to supply initial contents for a register.
On the Motorola 68000, a2 ... a5 should be suitable for global register variables, as should d3 ... d7. Of course, it will not do to use more than a few of those.
Note that a5 is used by OPTIMIZE_ROM_CALLS.
Local register variables in specific registers do not reserve the registers. The compiler's data flow analysis is capable of determining where the
specified registers contain live values, and where they are available for other uses. Stores into local register variables may be deleted when
they appear to be dead according to dataflow analysis. References to local register variables may be deleted or moved or simplified.
These local variables are sometimes convenient for use with the extended asm feature (see the section Assembler Instructions with C Expression Operands), if
you want to write one output of the assembler instruction directly into a particular register (this will work provided the register you specify fits the constraints
specified for that operand in the asm block).
You can define a local register variable with a specified register like this:
Here a5 is the name of the register which should be used. Note that this is the same syntax used for defining global register variables, but for a local variable it
would appear within a function.
Naturally the register name is cpu-dependent, but this is not a problem, since specific registers are most often useful with explicit assembler instructions (see
the section Assembler Instructions with C Expression Operands), which is CPU-specific as well, and since TIGCC only supports exactly one CPU (the Motorola
68000) anyway.
In addition, operating systems on one type of cpu may differ in how they name the registers; then you would need additional conditionals. For example, some
68000 operating systems call this register %a5.
Defining such a register variable does not reserve the register; it remains available for other uses in places where flow control determines the variable's value is
not live. However, these registers are made unavailable for use in the reload pass; excessive use of this feature leaves the compiler too few available registers
to compile certain functions.
This option does not guarantee that GCC will generate code that has this variable in the register you specify at all times. You may not code an explicit reference
to this register in an asm statement and assume it will always refer to this variable.
Stores into local register variables may be deleted when they appear to be dead according to dataflow analysis. References to local register variables may be
deleted or moved or simplified.
In TIGCC, it is possible to specify explictly where the parameters to a function a stored, in a syntax similar to global and local register
variables.
TIGCC can pass function parameters either on the stack or through registers. You can use the regparm attribute or the '-mregparm' compiler switch to let the
compiler automatically choose registers for the parameters, but you can also tell TIGCC to put a parameter into a specific register. This can be very handy when
interfacing with assembly code. For example, the following assembly function expects its 2 parameters in the d1 and d2 registers:
asm(".globl add
add:
move.l %d2,%d0
add.l %d1,%d0
rts");
Explicit register specifications for function parameters are also supported in function headers (not only in prototypes). Therefore, the assembly function above
could be replaced by the following C equivalent:
to pass a register parameter. The registers do not necessarily need to be call-clobbered. You can also use a2-a5/d3-d7 to pass a register parameter. But note
that the called function still has to save and restore those registers, even if they are used as arguments! In C code, TIGCC takes care of that automatically for
you, but in assembly code, it is something you need to remember.
Alternate Keywords
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 47 of 173
'-ansi' and the various '-std' options disable certain keywords. This causes trouble when you want to use GNU C extensions, or a general-purpose header file
that should be usable by all programs, including ISO C programs. The keywords asm, typeof and inline are not available in programs compiled with '-ansi' or
'-std' (although inline can be used in a program compiled with '-std=c99'). The ISO C99 keyword restrict is only available when '-std=gnu99' (which will
eventually be the default) or '-std=c99' (or the equivalent '-std=iso9899:1999') is used.
The way to solve these problems is to put __ at the beginning and end of each problematical keyword. For example, use __asm__ instead of asm, and
__inline__ instead of inline.
Other C compilers won't accept these alternative keywords; if you want to compile with another compiler, you can define the alternate keywords as macros to
replace them with the customary keywords. It looks like this:
#ifndef __GNUC__
#define __asm__ asm
#endif
'-pedantic' and other options cause warnings for many GNU C extensions. You can prevent such warnings within one expression by writing __extension__
before the expression. __extension__ has no effect aside from this.
You can define an enum tag without specifying its possible values. This results in an incomplete type, much like what you get if you write struct foo without
describing the elements. A later declaration which does specify the possible values completes the type.
You can't allocate variables or storage using the type while it is incomplete. However, you can work with pointers to that type.
This extension may not be very useful, but it makes the handling of enum more consistent with the way struct and union are handled.
GCC predefines two magic identifiers to hold the name of the current function. The identifier __FUNCTION__ holds the name of the function as it appears in the
source. The identifier __PRETTY_FUNCTION__ holds the name of the function pretty printed in a language specific fashion. (These names are always the same in
a C function, but in a C++ function they may be different; don't care about this, because TIGCC is not a C++ compiler.)
The compiler automatically replaces the identifiers with a string literal containing the appropriate name. Thus, they are neither preprocessor macros, like
__FILE__ and __LINE__, nor variables. This means that they catenate with other string literals, and that they can be used to initialize char arrays. For example
On the other hand, #ifdef __FUNCTION__ does not have any special meaning inside a function, since the preprocessor does not do anything special with the
identifier __FUNCTION__.
Note that these semantics are deprecated, and that GCC 3.2 will handle __FUNCTION__ and __PRETTY_FUNCTION__ the same way as __func__. __func__ is
defined by the ISO standard C99:
The identifier __func__ is implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration
appeared, where function-name is the name of the lexically-enclosing function. This name is the unadorned name of the function.
By this definition, __func__ is a variable, not a string literal. In particular, __func__ does not catenate with other string literals.
These functions may be used to get information about the callers of a function.
__builtin_return_address
__builtin_frame_address
__builtin_return_address
This function returns the return address of the current function, or of one of its callers. The level argument is number of frames to scan up the call stack. A
value of 0 yields the return address of the current function, a value of 1 yields the return address of the caller of the current function, and so forth. When
inlining the expected behavior is that the function will return the address of the function that will be returned to. To work around this behavior use the noinline
function attribute.
Sometimes (especially without a frame pointer) it may be impossible to determine the return address of any function other than the current one; in such cases,
or when the top of the stack has been reached, this function will return a random value. In addition, __builtin_frame_address may be used to determine if the
top of the stack has been reached.
This function should be used with a nonzero argument only for debugging purposes.
__builtin_frame_address
This function is similar to __builtin_return_address, but it returns the address of the function frame rather than the return address of the function. Calling
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 48 of 173
__builtin_frame_address with a value of 0 yields the frame address of the current function, a value of 1 yields the frame address of the caller of the current
function, and so forth.
The frame is the area on the stack which holds local variables and saved registers. The frame address is normally the address of the first word pushed on to the
stack by the function. However, the exact definition depends upon the processor and the calling convention. On the Motorola 68000, if the function has a frame,
then __builtin_frame_address will return the value of the frame pointer register a6 if level is 0.
This function should be used with a nonzero argument only for debugging purposes.
GCC provides a large number of built-in functions. Some of these are for internal use in the processing of exceptions or variable-length argument lists and will
not be documented here because they may change from time to time; we do not recommend general use of these functions.
__builtin_constant_p
__builtin_types_compatible_p
__builtin_choose_expr
__builtin_expect
__builtin_prefetch
GCC includes built-in versions of many of the functions in the standard C library. The versions prefixed with __builtin_ will always be treated as having the
same meaning as the C library function even if you specify the '-fno-builtin' option (see C Dialect Options). Many of these functions are only optimized in
certain cases; if they are not optimized in a particular case, a call to the library function will be emitted (but this does not make sense in TIGCC, as the standard
C library is not provided with it).
The functions abort, exit, _Exit and _exit are recognized and presumed not to return, but otherwise are not built in (TIGCC defines them as macros
anyway). _exit is not recognized in strict ISO C mode ('-ansi', '-std=c89' or '-std=c99'). _Exit is not recognized in strict C89 mode ('-ansi' or '-std=c89').
All these functions have corresponding versions prefixed with __builtin_, which may be used even in strict C89 mode.
Outside strict ISO C mode, the functions alloca, bcmp, bzero, index, rindex, ffs, fputs_unlocked, printf_unlocked and fprintf_unlocked may be
handled as built-in functions. All these functions have corresponding versions prefixed with __builtin_, which may be used even in strict C89 mode (in TIGCC,
alloca is built-in; other than that only __builtin_bzero might be useful).
The ISO C99 functions conj, conjf, conjl, creal, crealf, creall, cimag, cimagf, cimagl, imaxabs, llabs, snprintf, vscanf, vsnprintf and vsscanf are
handled as built-in functions except in strict ISO C90 mode. There are also built-in versions of the ISO C99 functions cosf, cosl, expf, expl, fabsf, fabsl,
logf, logl, sinf, sinl, sqrtf, and sqrtl, that are recognized in any mode since ISO C90 reserves these names for the purpose to which ISO C99 puts them.
All these functions have corresponding versions prefixed with __builtin_ (again, none of these are implemented in TIGCC).
The ISO C90 functions abs, cos, exp, fabs, fprintf, fputs, labs, log, memcmp, memcpy, memset, printf, putchar, puts, scanf, sin, snprintf, sprintf,
sqrt, sscanf, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncat, strncmp, strncpy, strpbrk, strrchr, strspn, strstr, vprintf and vsprintf are
all recognized as built-in functions unless '-fno-builtin' is specified (or '-fno-builtin-function' is specified for an individual function). All of these functions
have corresponding versions prefixed with __builtin_ (but most of these are defined as macros in TIGCC).
GCC provides built-in versions of the ISO C99 floating point comparison macros that avoid raising exceptions for unordered operands. They have the same
names as the standard macros (isgreater, isgreaterequal, isless, islessequal, islessgreater, and isunordered), with __builtin_ prefixed. The GNU
team intends for a library implementor to be able to simply #define each standard macro to its built-in equivalent.
__builtin_constant_p
You can use the built-in function __builtin_constant_p to determine if a value is known to be constant at compile-time and hence that GCC can perform
constant-folding on expressions involving that value. The argument of the function is the value to test. The function returns the integer 1 if the argument is
known to be a compile-time constant and 0 if it is not known to be a compile-time constant. A return of 0 does not indicate that the value is not a constant, but
merely that GCC cannot prove it is a constant with the specified value of the '-O' option.
If you have some complex calculation, you may want it to be folded if it involves constants, but need to call a function if it does not. For example:
#define Scale_Value(X) \
(__builtin_constant_p (X) \
? ((X) * SCALE + OFFSET) : Scale (X))
You may use this built-in function in either a macro or an inline function. However, if you use it in an inlined function and pass an argument of the function as
the argument to the built-in, GCC will never return 1 when you call the inline function with a string constant or compound literal (see Compound Literals) and
will not return 1 when you pass a constant numeric value to the inline function unless you specify the '-O' option.
You may also use __builtin_constant_p in initializers for static data. For instance, you can write
This is an acceptable initializer even if EXPRESSION is not a constant expression. GCC must be more conservative about evaluating the built-in in this case,
because it has no opportunity to perform optimization.
Previous versions of GCC did not accept this built-in in data initializers. The earliest version where it is completely safe is 3.0.1.
__builtin_types_compatible_p
You can use the built-in function __builtin_types_compatible_p to determine whether two types are the same.
This built-in function returns 1 if the unqualified versions of the types type1 and type2 (which are types, not expressions) are compatible, 0 otherwise. The
result of this built-in function can be used in integer constant expressions.
This built-in function ignores top level qualifiers (const, volatile, etc.). For example, int is equivalent to const int.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 49 of 173
The type int[] and int[5] are compatible. On the other hand, long int and char* are not compatible, although their sizes are the same. Also, the amount of
pointer indirection is taken into account when determining similarity. Consequently, short* is not similar to short**. Furthermore, two types that are
typedefed are considered compatible if their underlying types are compatible.
An enum type is considered to be compatible with another enum type. For example, enum {foo, bar} is similar to enum {hot, dog}.
You would typically use this function in code whose execution varies depending on the arguments' types. For example:
#define foo(x) \
({ \
typeof (x) tmp; \
if (__builtin_types_compatible_p (typeof (x), long double)) \
tmp = foo_long_double (tmp); \
else if (__builtin_types_compatible_p (typeof (x), double)) \
tmp = foo_double (tmp); \
else if (__builtin_types_compatible_p (typeof (x), float)) \
tmp = foo_float (tmp); \
else \
abort (); \
tmp; \
})
__builtin_choose_expr
You can use the built-in function __builtin_choose_expr to evaluate code depending on the value of a constant expression. This built-in function returns exp1 if
const_exp, which is a constant expression that must be able to be determined at compile time, is nonzero. Otherwise it returns 0.
This built-in function is analogous to the ? : operator in C, except that the expression returned has its type unaltered by promotion rules. Also, the built-in
function does not evaluate the expression that was not chosen. For example, if const_exp evaluates to true, exp2 is not evaluated even if it has side-effects.
This built-in function can return an lvalue if the chosen argument is an lvalue.
If exp1 is returned, the return type is the same as exp1's type. Similarly, if exp2 is returned, its return type is the same as exp2.
Example:
#define foo(x) \
__builtin_choose_expr ( \
__builtin_types_compatible_p (typeof (x), double), \
foo_double (x), \
__builtin_choose_expr ( \
__builtin_types_compatible_p (typeof (x), float), \
foo_float (x), \
/* The void expression results in a compile-time error \
when assigning the result to something. */ \
(void)0))
Note: The unused expression (exp1 or exp2 depending on the value of const_exp) may still generate syntax errors. This may change in future revisions.
__builtin_expect
You may use __builtin_expect to provide the compiler with branch prediction information.
The return value is the value of exp, which should be an integral expression. The value of c must be a compile-time constant. The semantics of the built-in are
that it is expected that exp == c. For example:
would indicate that we do not expect to call foo, since we expect x to be zero. Since you are limited to integral expressions for exp, you should use
constructions such as
__builtin_prefetch
This function is used to minimize cache-miss latency by moving data into a cache before it is accessed. As the Motorola 68000 processor does not have any
data prefetch instruction, this function is not useful in TIGCC.
Recently, the preprocessor has relaxed its treatment of escaped newlines. Previously, the newline had to immediately follow a backslash. The current
implementation allows whitespace in the form of spaces, horizontal and vertical tabs, and form feeds between the backslash and the subsequent newline. The
preprocessor issues a warning, but treats it as a valid escaped newline and combines the two lines to form a single logical line. This works within comments and
tokens, including multi-line strings, as well as between tokens. Comments are not treated as whitespace for the purposes of this relaxation, since they have not
yet been replaced with spaces.
As an extension, GNU CPP permits string literals to cross multiple lines without escaping the embedded newlines. Each embedded newline is replaced with a
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 50 of 173
single \n character in the resulting string literal, regardless of what form the newline took originally.
CPP currently allows such strings in directives as well (other than the #include family).
ISO C99 and ISO C++ allow declarations and code to be freely mixed within compound statements. As an extension, GCC also allows this in C89 mode. For
example, you could do:
int i;
/* ... */
i++;
int j = i + 2;
Each identifier is visible from where it is declared until the end of the enclosing block.
For compatibility with other compilers, GCC allows you to define a structure or union that contains, as fields, structures and unions without names. For
example:
struct {
int a;
union {
int b;
float c;
};
int d;
} foo;
In this example, the user would be able to access members of the unnamed union with code like foo.b. Note that only unnamed structs and unions are
allowed, you may not have, for example, an unnamed int.
You must never create such structures that cause ambiguous field definitions. For example, this structure:
struct {
int a;
struct {
int a;
};
} foo;
It is ambiguous which a is being referred to with foo.a. Such constructs are not supported and must be avoided. In the future, such constructs may be
detected and treated as compilation errors.
Both the C and C++ standard have the concept of volatile objects. These are normally accessed by pointers and used for accessing hardware. The standards
encourage compilers to refrain from optimizations concerning accesses to volatile objects that it might perform on non-volatile objects. The C standard leaves it
implementation defined as to what constitutes a volatile access. The C++ standard omits to specify this, except to say that C++ should behave in a similar
manner to C with respect to volatiles, where possible. The minimum either standard specifies is that at a sequence point all previous accesses to volatile objects
have stabilized and no subsequent accesses have occurred. Thus an implementation is free to reorder and combine volatile accesses which occur between
sequence points, but cannot do so for accesses across a sequence point. The use of volatiles does not allow you to violate the restriction on updating objects
multiple times within a sequence point.
In most expressions, it is intuitively obvious what is a read and what is a write. For instance
will cause a read of the volatile object pointed to by src and stores the value into the volatile object pointed to by dst. There is no guarantee that these reads
and writes are atomic, especially for objects larger than int.
Less obvious expressions are where something which looks like an access is used in a void context. An example would be,
With C, such expressions are rvalues, and as rvalues cause a read of the object, GCC interprets this as a read of the volatile being pointed to.
History
Copyright © 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Copyright © 2000, 2001, 2002 Zeljko Juric, Sebastian Reichelt, Kevin Kofler
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 51 of 173
This part of the documentation is a modified version of the Command-Line Options section of the GCC Manual. Therefore it is licensed under the GNU Free
Documentation License.
This section describes the options supported by gcc, the driver program of the GNU Compiler Collection, whose C compiler and assembler are used here. This
program is called either by tigcc or by the IDE. tigcc simulates some of these options itself, namely '-E', '-S', and '-c', and it also has some additional ones.
In the IDE, there is an item in the project settings where you can set the options described here, with some exceptions, including the switches mentioned
above.
TIGCC normally does preprocessing, compilation, assembly and linking all in one step, and finally produces a file which is executable on the calculator. The
"overall options" allow you to stop this process at an intermediate stage. For example, the '-c' option says not to run the linker. Then the output consists of
object files output by the assembler.
Other options are passed on to one stage of processing. Some options control the preprocessor and others the compiler itself. Yet other options control the
assembler and linker; most of these are not documented here, since you rarely need to use any of them. In fact, only those options which may be more or less
useful with TIGCC are mentioned here (although we didn't check whether all of them are really usable in TIGCC). For more info about standard options that are
recognized by the compiler, read the official manual.
We suggest that you use the '-O2' switch in all of your compilations; it increases speed and decreases the program size at the cost of compilation time.
tigcc accepts options and file names as operands. Many options have multi-letter names; therefore multiple single-letter options may not be grouped: '-dr' is
very different from '-d -r'.
You can mix options and other arguments. For the most part, the order you use doesn't matter. Order does matter when you use several options of the same
kind; for example, if you specify '-L' more than once, the directories are searched in the order specified.
Many options have long names starting with '-f' or with '-W' - for example, '-fforce-mem', '-fstrength-reduce', '-Wformat' and so on. Most of these have
both positive and negative forms; the negative form of '-ffoo' would be '-fno-foo'. This manual documents only one of these two forms, whichever one is not
the default.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version
published by the Free Software Foundation; with the Invariant Sections being "GNU General Public License" and "Funding Free Software", the Front-Cover texts
being (a) (see below), and with the Back-Cover Texts being (b) (see below). A copy of the license is included in the section entitled "GNU Free Documentation
License".
A GNU Manual
You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development.
These options apply only to the command line compiler. If you want to use the IDE instead, you do not need to worry about these topics.
tigcc has an important difference to the standard program gcc: tigcc always overwrites assembly or object files. For example, if a file test.c is compiled, the
files test.s and test.o will be created and overwritten if necessary, but they will automatically be deleted again if neither '-c' nor '-S' are specified.
Another important difference is that tigcc always looks for libraries in the 'Lib' subfolder of the installation.
-pack varname
Compress the file generated during compilation. varname is the name of the on-calc packed variable. Although varname cannot have an extension, the
variable on the calculator will always have the extension ppg. varname cannot be the same as the on-calc name of the program itself. When you use this
switch, two files will be created; one with the extension .89y or .9xy, and one .89z or .9xz file.
This option comes from Thomas Nussbaumer's TIGCC Tools Suite, where this feature is called "ExePack Technology." You can read about it on the official
TI-Chess Team site.
-q
Keep as quiet as possible while assembling and linking. This option is not needed by the compiler because it is always quiet, but the linker and especially
the assembler output some information.
-v0
This switch is an addition to the '-v' switch. It tells TIGCC to output only the commands that are run directly. This was the default in some previous
releases.
-g
The '-g' switch in GCC turns on debugging information; in TIGCC the COFF format will be used in all cases. If you use this option in TIGCC, the .s file will
not be deleted, but instead it will be filled with lines from the C source along with file offsets as comments.
-standalone
Do not link against tigcc.a. All of GCC's internal functions are implemented in this library, as well as all non-TIOS functions. Using one of these will result
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 52 of 173
-ar
Create an archive (a static library) instead of a program. The resulting file will have an .a ending.
-bsr
This option is ignored for compatibility.
In addition to these options, the tigcc program also accepts most of the linker options.
Compilation can involve up to four stages: preprocessing, compilation proper, assembly and linking, always in that order. The first three stages apply to an
individual source file, and end by producing an object file; linking combines all the object files (those newly compiled, and those specified as input) into an
executable file.
For any given input file, the file name suffix determines what kind of compilation is done (some of these apply only to TIGCC):
file.c
C source code which must be preprocessed.
file.s
GNU Assembler code.
file.S
GNU Assembler code which must be preprocessed.
file.asm
A68k Assembler code.
file.o
COFF object file to be linked using ld.
file.a
Static library (function archive) to be linked using ld.
You can specify the input language explicitly with the '-x' option:
-x language
Specify explicitly the language for the following input files (rather than letting the compiler choose a default based on the file name suffix). This option
applies to all following input files until the next '-x' option. Possible values for language are:
c c-header cpp-output c++ c++-cpp-output objective-c objc-cpp-output assembler assembler-with-cpp ada f77 f77-cpp-input ratfor
java treelang
-x none
Turn off any specification of a language, so that subsequent files are handled according to their file name suffixes (as they are if '-x' has not been used at
all).
-pass-exit-codes
Normally the gcc program will exit with the code of 1 if any phase of the compiler returns a non-success return code. If you specify '-pass-exit-codes',
the gcc program will instead return with numerically highest error produced by any phase that returned an error indication.
If you only want some of the stages of compilation, you can use '-x' (or filename suffixes) to tell gcc where to start, and one of the options '-c', '-S', or '-E' to
say where gcc is to stop. Note that some combinations (for example, '-x cpp-output -E') instruct gcc to do nothing at all.
-c
Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each
source file.
By default, the object file name for a source file is made by replacing the suffix .c, .i, .s, etc., with .o.
-S
Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembler code file for each non-assembler input file
specified.
By default, the assembler file name for a source file is made by replacing the suffix .c, .i, etc., with .s.
-E
Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard
output.
-o file
Place output in file file. This applies regardless to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler
file or preprocessed C code.
Since only one output file can be specified, it does not make sense to use '-o' when compiling more than one input file, unless you are producing an
executable file as output.
If '-o' is not specified, the default is to put an executable file in a.out, the object file for source.suffix in source.o, its assembler file in source.s, and
all preprocessed C source on standard output.
-v
Print (on standard error output) the commands executed to run the stages of compilation. Also print the version number of the compiler driver program
and of the preprocessor and the compiler proper.
-###
Like '-v' except the commands are not executed and all command arguments are quoted. This is useful for shell scripts to capture the driver-generated
command lines.
-pipe
Use pipes rather than temporary files for communication between the various stages of compilation. This fails to work on some systems where the
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 53 of 173
assembler is unable to read from a pipe; but the GNU assembler has no trouble.
--help
Print (on the standard output) a description of the command line options understood by gcc. If the '-v' option is also specified then '--help' will also be
passed on to the various processes invoked by gcc, so that they can display the command line options they accept. If the '-W' option is also specified
then command line options which have no documentation associated with them will also be displayed.
--target-help
Print (on the standard output) a description of target specific command line options for each tool.
--version
Display the version number and copyrights of the invoked GCC.
The following options control the dialect of C that the compiler accepts:
-ansi
Support all ISO C89 programs. This turns off certain features of GCC that are incompatible with ISO C89, such as the asm and typeof keywords, and
some predefined macros that identify the type of system you are using. It also enables the undesirable and rarely used ISO trigraph feature, and disables
recognition of C++ style // comments as well as the inline keyword.
The alternate keywords __asm__, __extension__, __inline__ and __typeof__ continue to work despite '-ansi'. You would not want to use them in an
ISO C program, of course, but it is useful to put them in header files that might be included in compilations done with '-ansi'. Alternate predefined
macros such as __unix__ are also available, with or without '-ansi'.
The '-ansi' option does not cause non-ISO programs to be rejected gratuitously. For that, '-pedantic' is required in addition to '-ansi'. See Warning
Options.
The macro __STRICT_ANSI__ is predefined when the '-ansi' option is used. Some header files may notice this macro and refrain from declaring certain
functions or defining certain macros that the ISO standard doesn't call for; this is to avoid interfering with any programs that might use these names for
other things.
Functions which would normally be built in but do not have semantics defined by ISO C (such as alloca) are not built-in functions with '-ansi' is used. See
Other built-in functions provided by GCC for details of the functions affected.
Note: At the moment, the TIGCC library depends heavily on GNU C extensions, so you cannot use the '-ansi' switch in TIGCC.
-std=standard
Determine the language standard. A value for standard must be provided; provided; possible values are
c89
iso9899:1990
ISO C90 (same as '-ansi').
iso9899:199409
ISO C90 as modified in amendment 1.
c99
c9x
iso9899:1999
iso9899:199x
ISO C99. Note that this standard is not yet fully supported; see http://gcc.gnu.org/gcc-3.3/c99status.html for more information. The names c9x
and iso9899:199x are deprecated.
gnu89
Default, ISO C90 plus GNU extensions (including some C99 features).
gnu99
gnu9x
ISO C99 plus GNU extensions. When ISO C99 is fully implemented in GCC, this will become the default. The name gnu9x is deprecated.
Even when this option is not specified, you can still use some of the features of newer standards in so far as they do not conflict with previous C
standards. For example, you may use __restrict__ even when '-std=c99' is not specified.
The '-std' options specifying some version of ISO C have the same effects as '-ansi', except that features that were not in ISO C90 but are in the
specified version (for example, // comments and the inline keyword in ISO C99) are not disabled.
-aux-info filename
Output to the given filename prototyped declarations for all functions declared and/or defined in a translation unit, including those in header files. This
option is silently ignored in any language other than C.
Besides declarations, the file indicates, in comments, the origin of each declaration (source file and line), whether the declaration was implicit, prototyped
or unprototyped (I, N for new or O for old, respectively, in the first character after the line number and the colon), and whether it came from a declaration
or a definition (C or F, respectively, in the following character). In the case of function definitions, a K&R-style list of arguments followed by their
declarations is also provided, inside comments, after the declaration.
-fno-asm
Do not recognize asm, inline or typeof as a keyword, so that code can use these words as identifiers. You can use the keywords __asm__, __inline__
and __typeof__ instead. '-ansi' implies '-fno-asm'.
-fno-builtin
-fno-builtin-function
Don't recognize built-in functions that do not begin with __builtin_ as prefix. See Other built-in functions provided by GCC for details of the functions
affected, including those which are not built-in functions when '-ansi' or '-std' options for strict ISO C conformance are used because they do not have
an ISO standard meaning.
GCC normally generates special code to handle certain built-in functions more efficiently; for instance, calls to alloca may become single instructions that
adjust the stack directly. The resulting code is often both smaller and faster, but since the function calls no longer appear as such, you cannot set a
breakpoint on those calls, nor can you change the behavior of the functions by linking with a different library.
With the '-fno-builtin-function' option, only the built-in function function is disabled. function must not begin with __builtin_. If a function is named
this is not built-in in this version of GCC, this option is ignored. There is no corresponding '-fbuiltin-function' option; if you wish to enable built-in
functions selectively when using '-fno-builtin' or '-ffreestanding', you may define macros such as:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 54 of 173
-fhosted
Assert that compilation takes place in a hosted environment. This implies '-fbuiltin'. A hosted environment is one in which the entire standard library is
available, and in which main has a return type of int. Examples are nearly everything except a kernel. This is equivalent to '-fno-freestanding'.
Although TI calculators are not really hosted environments, '-fhosted' is kept as the default.
-ffreestanding
Assert that compilation takes place in a freestanding environment. This implies '-fno-builtin'. A freestanding environment is one in which the standard
library may not exist, and program startup may not necessarily be at main. The most obvious example is an OS kernel. This is equivalent to '-fno-
hosted'.
-fms-extensions
Accept some non-standard constructs used in Microsoft header files.
-trigraphs
Support ISO C trigraphs. The '-ansi' option (and '-std' options for strict ISO C conformance) implies '-trigraphs'. See Options Controlling the
Preprocessor for more information.
-no-integrated-cpp
Performs a compilation in two passes: preprocessing and compiling. This option allows a user supplied "cc1" via the '-B' option. The user supplied
compilation step can then add in an additional preprocessing step after normal preprocessing but before compiling. The default is to use the integrated
preprocessor.
The semantics of this option will change if "cc1", "cc1plus", and "cc1obj" are merged.
-traditional
-traditional-cpp
Formerly, these options caused GCC to attempt to emulate a pre-standard C compiler. They are now only supported with the '-E' switch. The
preprocessor continues to support a pre-standard mode.
-fcond-mismatch
Allow conditional expressions with mismatched types in the second and third arguments. The value of such an expression is void.
-funsigned-char
Let the type char be unsigned, like unsigned char. In TIGCC, the default is signed char.
Ideally, a portable program should always use signed char or unsigned char when it depends on the signedness of an object. But many programs have
been written to use plain char and expect it to be signed, or expect it to be unsigned, depending on the machines they were written for. This option, and
its inverse, let you make such a program work with the opposite default.
The type char is always a distinct type from each of signed char or unsigned char, even though its behavior is always just like one of those two.
-fsigned-char
Let the type char be signed, like signed char.
Note that this is equivalent to '-fno-unsigned-char', which is the negative form of '-funsigned-char'. Likewise, the option '-fno-signed-char' is
equivalent to '-funsigned-char'.
-fsigned-bitfields
-funsigned-bitfields
-fno-signed-bitfields
-fno-unsigned-bitfields
These options control whether a bit-field is signed or unsigned, when the declaration does not use either signed or unsigned. By default, such a bit-field
is signed, because this is consistent: the basic integer types such as int are signed types.
-fwritable-strings
Store string constants in the writable data segment and don't uniquize them. This is for compatibility with old programs which assume they can write into
string constants.
Writing into string constants is a very bad idea; "constants" should be constant.
Warnings are diagnostic messages that report constructions which are not inherently erroneous but which are risky or suggest there may have been an error.
You can request many specific warnings with options beginning '-W', for example '-Wimplicit' to request warnings on implicit declarations. Each of these
specific warning options also has a negative form beginning '-Wno-' to turn off warnings; for example, '-Wno-implicit'. This manual lists only one of the two
forms, whichever is not the default.
The following options control the amount and kinds of warnings produced by GCC.
-fsyntax-only
Check the code for syntax errors, but don't do anything beyond that.
-pedantic
Issue all the warnings demanded by strict ISO C; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C.
This option follows the version of the ISO C standard specified by any '-std' option used.
Valid ISO C programs should compile properly with or without this option (though a rare few will require '-ansi' or a '-std' option specifying the required
version of ISO C). However, without this option, certain GNU extensions and traditional C features are supported as well. With this option, they are
rejected.
'-pedantic' does not cause warning messages for use of the alternate keywords whose names begin and end with __. Pedantic warnings are also disabled
in the expression that follows __extension__. However, only system header files should use these escape routes; application programs should avoid
them. See Alternate Keywords.
Some users try to use '-pedantic' to check programs for strict ISO C conformance. They soon find that it does not do quite what they want: it finds some
non-ISO practices, but not all - only those for which ISO C requires a diagnostic, and some others for which diagnostics have been added.
A feature to report any failure to conform to ISO C might be useful in some instances, but would require considerable additional work and would be quite
different from '-pedantic'. The GNU team doesn't have plans to support such a feature in the near future.
Where the standard specified with '-std' represents a GNU extended dialect of C, such as gnu89 or gnu99, there is a corresponding base standard, the
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 55 of 173
version of ISO C on which the GNU extended dialect is based. Warnings from '-pedantic' are given where they are required by the base standard. (It
would not make sense for such warnings to be given only for features not in the specified GNU C dialect, since by definition the GNU dialects of C include
all features the compiler supports with the given option, and there would be nothing to warn about.)
-pedantic-errors
Like '-pedantic', except that errors are produced rather than warnings.
-w
Inhibit all warning messages.
-Wno-import
Inhibit warning messages about the use of #import.
-Wchar-subscripts
Warn if an array subscript has type char. This is a common cause of error, as programmers often forget that this type is signed on some machines.
-Wcomment
Warn whenever a comment-start sequence /* appears in a /* comment, or whenever a Backslash-Newline appears in a // comment.
-Wformat
Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified, and that the
conversions specified in the format string make sense. This includes standard functions, and others specified by format attributes (see format).
Since '-Wformat' also checks for null format arguments for several functions, '-Wformat' also implies '-Wnonnull'.
'-Wformat' is included in '-Wall'. For more control over some aspects of format checking, the options '-Wno-format-extra-args', '-Wno-format-
zero-length', '-Wformat-nonliteral', '-Wformat-security', and '-Wformat=2' are available, but are not included in '-Wall'.
-Wno-format-extra-args
If '-Wformat' is specified, do not warn about excess arguments to a printf or scanf format function. The C standard specifies that such arguments are
ignored.
-Wno-format-zero-length
If '-Wformat' is specified, do not warn about zero-length formats. The C standard specifies that zero-length formats are allowed.
-Wformat-nonliteral
If '-Wformat' is specified, also warn if the format string is not a string literal and so cannot be checked, unless the format function takes its format
arguments as a va_list.
-Wformat-security
If '-Wformat' is specified, also warn about uses of format functions that represent possible security problems. At present, this warns about calls to printf
and scanf functions where the format string is not a string literal and there are no format arguments, as in printf (foo);. This may be a security hole if
the format string came from untrusted input and contains %n. (This is currently a subset of what '-Wformat-nonliteral' warns about, but in future
warnings may be added to '-Wformat-security' that are not included in '-Wformat-nonliteral'.)
-Wformat=2
Enable '-Wformat' plus format checks not included in '-Wformat'. Currently equivalent to '-Wformat -Wformat-nonliteral -Wformat-security'.
-Wnonnull
Enable warning about passing a null pointer for arguments marked as requiring a non-null value by the nonnull function attribute.
'-Wnonnull' is included in '-Wall' and '-Wformat'. It can be disabled with the '-Wno-nonnull' option.
-Wimplicit-int
Warn when a declaration does not specify a type.
-Wimplicit-function-declaration
-Werror-implicit-function-declaration
Give a warning (or error) whenever a function is used before being declared.
-Wimplicit
Same as '-Wimplicit-int -Wimplicit-function-declaration'.
-Wmissing-braces
Warn if an aggregate or union initializer is not fully bracketed. In the following example, the initializer for a is not fully bracketed, but that for b is fully
bracketed.
int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 0, 1 }, { 2, 3 } };
-Wparentheses
Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected, or when operators
are nested whose precedence people often get confused about.
Also warn about constructions where there may be confusion to which if statement an else branch belongs. Here is an example of such a case:
{
if (a)
if (b)
foo ();
else
bar ();
}
In C, every else branch belongs to the innermost possible if statement, which in this example is if (b). This is often not what the programmer
expected, as illustrated in the above example by the indentation the programmer chose. When there is the potential for this confusion, GCC will issue a
warning when this flag is specified. To eliminate the warning, add explicit braces around the innermost if statement so there is no way the else could
belong to the enclosing if. The resulting code would look like this:
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
-Wsequence-point
Warn about code that may have undefined semantics because of violations of sequence point rules in the C standard.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 56 of 173
The C standard defines the order in which expressions in a C program are evaluated in terms of sequence points, which represent a partial ordering
between the execution of parts of the program: those executed before the sequence point, and those executed after it. These occur after the evaluation of
a full expression (one which is not part of a larger expression), after the evaluation of the first operand of a &&, ||, ? : or , (comma) operator, before a
function is called (but after the evaluation of its arguments and the expression denoting the called function), and in certain other places. Other than as
expressed by the sequence point rules, the order of evaluation of subexpressions of an expression is not specified. All these rules describe only a partial
order rather than a total order, since, for example, if two functions are called within one expression with no sequence point between them, the order in
which the functions are called is not specified. However, the standards committee have ruled that function calls do not overlap.
It is not specified when between sequence points modifications to the values of objects take effect. Programs whose behavior depends on this have
undefined behavior; the C standard specifies that "Between the previous and next sequence point an object shall have its stored value modified at most
once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.". If a program breaks these
rules, the results on any particular implementation are entirely unpredictable.
Examples of code with undefined behavior are a = a++;, a[n] = b[n++] and a[i++] = i;. Some more complicated cases are not diagnosed by this
option, and it may give an occasional false positive result, but in general it has been found fairly effective at detecting this sort of problem in programs.
The C standard is worded confusingly, therefore there is some debate over the precise meaning of the sequence point rules in subtle cases. Links to
discussions of the problem, including proposed formal definitions, may be found on the GCC readings page, at http://gcc.gnu.org/readings.html.
-Wreturn-type
Warn whenever a function is defined with a return-type that defaults to int. Also warn about any return statement with no return-value in a function
whose return-type is not void.
-Wswitch
Warn whenever a switch statement has an index of enumeral type and lacks a case for one or more of the named codes of that enumeration. (The
presence of a default label prevents this warning.) case labels outside the enumeration range also provoke warnings when this option is used.
-Wswitch-default
Warn whenever a switch statement does not have a default case.
-Wswitch-enum
Warn whenever a switch statement has an index of enumeral type and lacks a case for one or more of the named codes of that enumeration. case labels
outside the enumeration range also provoke warnings when this option is used.
-Wtrigraphs
Warn if any trigraphs are encountered that might change the meaning of the program (trigraphs within comments are not warned about). For more
information about trigraphs, see Options Controlling the Preprocessor.
-Wunused-function
Warn whenever a static function is declared but not defined or a non\-inline static function is unused.
-Wunused-label
Warn whenever a label is declared but not used.
-Wunused-parameter
Warn whenever a function parameter is unused aside from its declaration.
-Wunused-variable
Warn whenever a local variable or non-constant static variable is unused aside from its declaration
-Wunused-value
Warn whenever a statement computes a result that is explicitly not used.
-Wunused
All the above '-Wunused' options combined.
In order to get a warning about an unused function parameter, you must either specify '-W -Wunused' or separately specify '-Wunused-parameter'.
-Wuninitialized
Warn if an automatic variable is used without first being initialized or if a variable may be clobbered by a setjmp call (I am not sure whether setjmp
problems may be detected in TIGCC).
These warnings are possible only in optimizing compilation, because they require data flow information that is computed only when optimizing. If you
don't specify '-O', you simply won't get these warnings.
These warnings occur only for variables that are candidates for register allocation. Therefore, they do not occur for a variable that is declared volatile,
or whose address is taken, or whose size is other than 1, 2, 4 or 8 bytes. Also, they do not occur for structures, unions or arrays, even when they are in
registers.
Note that there may be no warning about a variable that is used only to compute a value that itself is never used, because such computations may be
deleted by data flow analysis before the warnings are printed.
These warnings are made optional because GCC is not smart enough to see all the reasons why the code might be correct despite appearing to have an
error. Here is one example of how this can happen:
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
If the value of y is always 1, 2 or 3, then x is always initialized, but GCC doesn't know this. Here is another common case:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 57 of 173
{
int save_y;
if (change_y) save_y = y, y = new_y;
...
if (change_y) y = save_y;
}
This option also warns when a non-volatile automatic variable might be changed by a call to longjmp. These warnings as well are possible only in
optimizing compilation (although I am not sure whether they can be caught at all in TIGCC).
The compiler sees only the calls to setjmp. It cannot know where longjmp will be called; in fact, an interrupt handler could call it at any point in the code.
As a result, you may get a warning even when there is in fact no problem because longjmp cannot in fact be called at the place which would cause a
problem.
Some spurious warnings can be avoided if you declare all the functions you use that never return as noreturn.
-Wunknown-pragmas
Warn when a #pragma directive is encountered which is not understood by GCC. If this command line option is used, warnings will even be issued for
unknown pragmas in system header files. This is not the case if the warnings were only enabled by the '-Wall' command line option.
-Wstrict-aliasing
This option is only active when '-fstrict-aliasing' is active. It warns about code which might break the strict aliasing rules that the compiler is using for
optimization. The warning does not catch all cases, but does attempt to catch the more common pitfalls. It is included in '-Wall'.
-Wall
All of the above '-W' options combined. This enables all the warnings about constructions that some users consider questionable, and that are easy to
avoid (or modify to prevent the warning), even in conjunction with macros.
The following '-W...' options are not implied by '-Wall'. Some of them warn about constructions that users generally do not consider questionable, but which
occasionally you might wish to check for; others warn about constructions that are necessary or hard to avoid in some cases, and there is no simple way to
modify the code to suppress the warning.
-W
Print extra warning messages for these events:
A function can return either with or without a value. (Falling off the end of the function body is considered returning without a value.) For example,
this function would evoke such a warning:
foo (a)
{
if (a > 0)
return a;
}
An expression-statement or the left-hand side of a comma expression contains no side effects. To suppress the warning, cast the unused expression
to void. For example, an expression such as x[i,j] will cause a warning, but x[(void)i,j] will not.
A comparison like x<=y<=z appears; this is equivalent to (x<=y ? 1 : 0) <= z, which is a different interpretation from that of ordinary
mathematical notation.
Storage-class specifiers like static are not the first things in a declaration. According to the C Standard, this usage is obsolescent.
The return type of a function has a type qualifier such as const. Such a type qualifier has no effect, since the value returned by a function is not an
lvalue. (But don't warn about the GNU extension of volatile void return types. That extension will be warned about if '-pedantic' is specified.)
A comparison between signed and unsigned values could produce an incorrect result when the signed value is converted to unsigned. (But don't
warn if '-Wno-sign-compare' is also specified.)
An aggregate has a partly bracketed initializer. For example, the following code would evoke such a warning, because braces are missing around the
initializer for x.h:
struct s { int f, g; };
struct t { struct s h; int i; };
struct t x = { 1, 2, 3 };
An aggregate has an initializer which does not initialize all members. For example, the following code would cause such a warning, because x.h
would be implicitly initialized to zero:
struct s { int f, g, h; };
struct s x = { 3, 4 };
-Wno-div-by-zero
Do not warn about compile-time integer division by zero. Floating point division by zero is not warned about, as it can be a legitimate way of obtaining
infinities and NaNs.
-Wsystem-headers
Print warning messages for constructs found in system header files. Warnings from system headers are normally suppressed, on the assumption that they
usually do not indicate real problems and would only make the compiler output harder to read. Using this command line option tells GCC to emit warnings
from system headers as if they occurred in user code. However, note that using '-Wall' in conjunction with this option will not warn about unknown
pragmas in system headers - for that, '-Wunknown-pragmas' must also be used.
Note that the TIGCC Library header files are not included as system header files.
-Wfloat-equal
Warn if floating point values are used in equality comparisons.
The idea behind this is that sometimes it is convenient (for the programmer) to consider floating-point values as approximations to infinitely precise real
numbers. If you are doing this, then you need to compute (by analyzing the code, or in some other way) the maximum or likely maximum error that the
computation introduces, and allow for it when performing comparisons (and when producing output, but that's a different problem). In particular, instead
of testing for equality, you would check to see whether the two values have ranges that overlap; and this is done with the relational operators, so equality
comparisons are probably mistaken.
-Wtraditional
Warn about certain constructs that behave differently in traditional and ISO C. Also warn about ISO C constructs that have no traditional C equivalent,
and/or problematic constructs which should be avoided.
Macro parameters that appear within string literals in the macro body. In traditional C macro replacement takes place within string literals, but does
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 58 of 173
not in ISO C.
In traditional C, some preprocessor directives did not exist. Traditional preprocessors would only consider a line to be a directive if the # appeared in
column 1 on the line. Therefore '-Wtraditional' warns about directives that traditional C understands but would ignore because the # does not
appear as the first character on the line. It also suggests you hide directives like #pragma not understood by traditional C by indenting them. Some
traditional implementations would not recognize #elif, so it suggests avoiding it altogether.
The U integer constant suffix, or the F or L floating point constant suffixes. (Traditional C does support the L suffix on integer constants.) Note,
these suffixes appear in macros defined in limits.h, for example.
A function declared external in one block and then used after the end of the block.
A non-static function declaration follows a static one. This construct is not accepted by some traditional C compilers.
The ISO type of an integer constant has a different width or signedness from its traditional type. This warning is only issued if the base of the
constant is 10, i.e. hexadecimal or octal values, which typically represent bit patterns, are not warned about.
Identifier conflicts with labels. Traditional C lacks a separate namespace for labels.
Initialization of unions. If the initializer is zero, the warning is omitted. This is done under the assumption that the zero initializer in user code
appears conditioned on e.g. __STDC__ to avoid missing initializer warnings and relies on default initialization to zero in the traditional C case.
Conversions by prototypes between fixed/floating point values and vice versa. The absence of these prototypes when compiling with traditional C
would cause serious problems. This is a subset of the possible conversion warnings, for the full set use '-Wconversion'.
Use of ISO C style function definitions. This warning intentionally is not issued for prototype declarations or variadic functions because these ISO C
features will appear in your code when using libiberty's traditional C compatibility macros, PARAMS and VPARAMS. This warning is also bypassed for
nested functions because that feature is already a gcc extension and thus not relevant to traditional C compatibility.
-Wundef
Warn if an undefined identifier is evaluated in an #if directive.
-Wendif-labels
Warn whenever an #else or an #endif are followed by text.
-Wshadow
Warn whenever a local variable shadows another local variable, parameter or global variable or whenever a built-in function is shadowed.
-Wlarger-than-len
Warn whenever an object of larger than len bytes is defined.
-Wpointer-arith
Warn about anything that depends on the "size of" a function type or of void. GNU C assigns these types a size of 1, for convenience in calculations with
void* pointers and pointers to functions.
-Wbad-function-cast
Warn whenever a function call is cast to a non-matching type. For example, warn if int malloc() is cast to anything *.
-Wcast-qual
Warn whenever a pointer is cast so as to remove a type qualifier from the target type. For example, warn if a const char * is cast to an ordinary
char *.
-Wcast-align
Warn whenever a pointer is cast such that the required alignment of the target is increased. For example, warn if a char * is cast to an int * on
machines where integers can only be accessed at two- or four-byte boundaries.
-Wwrite-strings
When compiling C, give string constants the type const char[length] so that copying the address of one into a non-const char * pointer will get a
warning; when compiling C++, warn about the deprecated conversion from string constants to char *. These warnings will help you find at compile time
code that can try to write into a string constant, but only if you have been very careful about using const in declarations and prototypes. Otherwise, it will
just be a nuisance; this is why we did not make '-Wall' request these warnings.
-Wconversion
Warn if a prototype causes a type conversion that is different from what would happen to the same argument in the absence of a prototype. This includes
conversions of fixed point to floating and vice versa, and conversions changing the width or signedness of a fixed point argument except when the same
as the default promotion.
Also, warn if a negative integer constant expression is implicitly converted to an unsigned type. For example, warn about the assignment x = -1 if x is
unsigned. But do not warn about explicit casts like (unsigned) -1.
-Wsign-compare
Warn when a comparison between signed and unsigned values could produce an incorrect result when the signed value is converted to unsigned. This
warning is enabled by '-W', and by '-Wall' in C++ only.
-Waggregate-return
Warn if any functions that return structures or unions are defined or called.
-Wstrict-prototypes
Warn if a function is declared or defined without specifying the argument types. (An old-style function definition is permitted without a warning if
preceded by a declaration which specifies the argument types.)
-Wmissing-prototypes
Warn if a global function is defined without a previous prototype declaration. This warning is issued even if the definition itself provides a prototype. The
aim is to detect global functions that fail to be declared in header files.
-Wmissing-declarations (C only)
Warn if a global function is defined without a previous declaration. Do so even if the definition itself provides a prototype. Use this option to detect global
functions that are not declared in header files.
-Wmissing-noreturn
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 59 of 173
Warn about functions which might be candidates for attribute noreturn. Note these are only possible candidates, not absolute ones. Care should be taken
to manually verify functions actually do not ever return before adding the noreturn attribute, otherwise subtle code generation bugs could be introduced.
-Wmissing-format-attribute
If '-Wformat' is enabled, also warn about functions which might be candidates for format attributes. Note these are only possible candidates, not
absolute ones. GCC will guess that format attributes might be appropriate for any function that calls a function like vprintf or vscanf, but this might not
always be the case, and some functions for which format attributes are appropriate may not be detected. This option has no effect unless '-Wformat' is
enabled (possibly by '-Wall').
-Wno-multichar
Do not warn if a multicharacter constant ('FOOF') is used. Usually they indicate a typo in the user's code, as they have implementation-defined values,
and should not be used in portable code.
-Wno-deprecated-declarations
Do not warn about uses of functions, variables, and types marked as deprecated by using the deprecated attribute.
-Wpacked
Warn if a structure is given the packed attribute, but the packed attribute has no effect on the layout or size of the structure. Such structures may be
mis-aligned for little benefit. For instance, in this code, the variable f.x in struct bar will be misaligned even though struct bar does not itself have the
packed attribute:
struct foo {
int x;
char a, b, c, d;
} __attribute__((packed));
struct bar {
char z;
struct foo f;
};
-Wpadded
Warn if padding is included in a structure, either to align an element of the structure or to align the whole structure. Sometimes when this happens it is
possible to rearrange the fields of the structure to reduce the padding and so make the structure smaller.
-Wredundant-decls
Warn if anything is declared more than once in the same scope, even in cases where multiple declaration is valid and changes nothing.
-Wnested-externs
Warn if an extern declaration is encountered within a function.
-Wunreachable-code
Warn if the compiler detects that code will never be executed.
This option is intended to warn when the compiler detects that at least a whole line of source code will never be executed, because some condition is
never satisfied or because it is after a procedure that never returns.
It is possible for this option to produce a warning even though there are circumstances under which part of the affected line can be executed, so care
should be taken when removing apparently-unreachable code.
For instance, when a function is inlined, a warning may mean that the line is unreachable in only one inlined copy of the function.
This option is not made part of '-Wall' because in a debugging version of a program there is often substantial code which checks correct functioning of
the program and is, hopefully, unreachable because the program does work. Another common use of unreachable code is to provide behavior which is
selectable at compile-time.
-Winline
Warn if a function can not be inlined and it was declared as inline. Even with this option, the compiler will not warn about failures to inline functions
declared in system headers.
The compiler uses a variety of heuristics to determine whether or not to inline a function. For example, the compiler takes into account the size of the
function being inlined and the the amount of inlining that has already been done in the current function. Therefore, seemingly insignificant changes in the
source program can cause the warnings produced by '-Winline' to appear or disappear.
-Wlong-long
Warn if long long type is used. This is default. To inhibit the warning messages, use '-Wno-long-long'. Flags '-Wlong-long' and '-Wno-long-long'
are taken into account only when '-pedantic' flag is used.
-Wdisabled-optimization
Warn if a requested optimization pass is disabled. This warning does not generally indicate that there is anything wrong with your code; it merely
indicates that GCC's optimizers were unable to handle the code effectively. Often, the problem is that your code is too big or too complex; GCC will refuse
to optimize programs when the optimization itself is likely to take inordinate amounts of time.
-Werror
Make all warnings into errors.
GCC has various special options that are used for debugging either your program or GCC. However, this manual is not meant to explain anything about the
internals of GCC, so you will have to go to the official version of this page on the internet if you want to debug GCC itself.
Currently there is no debugger for TIGCC programs, so most of these options make sense only if you plan to use their output directly.
-g
Produce debugging information in the operating system's native format (stabs is the default for the MC68000). GDB can work with this debugging
information. Note that tigcc handles this switch differently; see Options Available in the Command Line Compiler.
Unlike most other C compilers, GCC allows you to use '-g' with '-O'. The shortcuts taken by optimized code may occasionally produce surprising results:
some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; some statements may not be executed
because they compute constant results or their values were already at hand; some statements may execute in different places because they were moved
out of loops.
Nevertheless it proves possible to debug optimized output. This makes it reasonable to use the optimizer for programs that might have bugs.
The following options are useful when GCC is generated with the capability for more than one debugging format.
-ggdb
Produce debugging information for use by GDB. This means to use the most expressive format available, including GDB extensions if at all possible. Note
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 60 of 173
-gstabs
Produce debugging information in stabs format.
-gstabs+
Produce debugging information in stabs format, using GNU extensions understood only by the GNU debugger (GDB).
-gcoff
Produce debugging information in COFF format.
-glevel
-ggdblevel
-gstabslevel
-gcofflevel
Request debugging information and also use level to specify how much information. The default level is 2.
Level 1 produces minimal information, enough for making backtraces in parts of the program that you don't plan to debug. This includes descriptions of
functions and external variables, but no information about local variables and no line numbers.
Level 3 includes extra information, such as all the macro definitions present in the program. Some debuggers support macro expansion when you use '-
g3'.
-p
Generate extra code to write profile information suitable for the analysis program prof. You must use this option when compiling the source files you
want data about, and you must also use it when linking. This option is probably useless in TIGCC.
-pg
Generate extra code to write profile information suitable for the analysis program gprof. You must use this option when compiling the source files you
want data about, and you must also use it when linking. This option is probably useless in TIGCC.
-Q
Makes the compiler print out each function name as it is compiled, and print some statistics about each pass when it finishes.
-save-temps
Store the usual "temporary" intermediate files permanently; place them in the current directory and name them based on the source file. Thus, compiling
foo.c with '-c -save-temps' would produce files foo.i and foo.s, as well as foo.o. This creates a preprocessed foo.i output file even though the
compiler now normally uses an integrated preprocessor.
Without any optimization option, the compiler's goal is to reduce the cost of compilation and to make debugging produce the expected results. Statements are
independent: if you stop the program with a breakpoint between statements, you can then assign a new value to any variable or change the program counter
to any other statement in the function and get exactly the results you would expect from the source code. (This statement is currently meaningless for TIGCC,
because there is no integrated debugger yet.)
Turning on optimization flags makes the compiler attempt to improve the performance and/or code size at the expense of compilation time and possibly the
ability to debug the program.
Not all optimizations are controlled directly by a flag. Only optimizations that have a flag are listed.
-O
-O1
Optimize. Optimizing compilation takes somewhat more time, and a lot more memory for a large function.
With '-O', the compiler tries to reduce code size and execution time, without performing any optimizations that take a great deal of compilation time.
'-O' turns on the following optimization flags: -fdefer-pop -fmerge-constants -fthread-jumps -floop-optimize -fcrossjumping -fif-conversion -fif-
conversion2 -fdelayed-branch -fguess-branch-probability -fcprop-registers
'-O' also turns on '-fomit-frame-pointer' on machines where doing so does not interfere with debugging.
-O2
Optimize even more. GCC performs nearly all supported optimizations that do not involve a space-speed tradeoff. The compiler does not perform loop
unrolling or function inlining when you specify '-O2'. As compared to '-O', this option increases both compilation time and the performance of the
generated code.
'-O2' turns on all optimization flags specified by '-O'. It also turns on the following optimization flags:
-fforce-mem -foptimize-sibling-calls -fstrength-reduce -fcse-follow-jumps -fcse-skip-blocks -frerun-cse-after-loop -frerun-loop-
opt -fgcse -fgcse-lm -fgcse-sm -fdelete-null-pointer-checks -fexpensive-optimizations -fregmove -fschedule-insns -fschedule-insns2
-fsched-interblock -fsched-spec -fcaller-saves -fpeephole2 -freorder-blocks -freorder-functions -fstrict-aliasing -falign-
functions -falign-jumps -falign-loops -falign-labels
Please note the warning under '-fgcse' about invoking '-O2' on programs that use computed gotos.
-O3
Optimize yet more. '-O3' turns on all optimizations specified by '-O2' and also turns on the '-finline-functions' and '-frename-registers' options.
-O0
Do not optimize. This is the default.
-Os
Optimize for size. '-Os' enables all '-O2' optimizations that do not typically increase code size. It also performs further optimizations designed to reduce
code size.
'-Os' disables the following optimization flags: -falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -fprefetch-loop-arrays
If you use multiple '-O' options, with or without level numbers, the last such option is the one that is effective.
Options of the form '-fflag' specify machine-independent flags. Most flags have both positive and negative forms; the negative form of '-ffoo' would be '-fno-
foo'. In the table below, only one of the forms is listed: the one you typically will use. You can figure out the other form by either removing 'no-' or adding it.
The following options control specific optimizations. They are either activated by '-O' options or are related to ones that are. You can use the following flags in
the rare cases when "fine-tuning" of optimizations to be performed is desired.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 61 of 173
-fno-defer-pop
Always pop the arguments to each function call as soon as that function returns. For machines which must pop arguments after a function call, the
compiler normally lets arguments accumulate on the stack for several function calls and pops them all at once.
-fforce-mem
Force memory operands to be copied into registers before doing arithmetic on them. This produces better code by making all memory references potential
common subexpressions. When they are not common subexpressions, instruction combination should eliminate the separate register-load.
-fforce-addr
Force memory address constants to be copied into registers before doing arithmetic on them. This may produce better code just as '-fforce-mem' may.
-fomit-frame-pointer
Don't keep the frame pointer in a register for functions that don't need one. This avoids the instructions to save, set up and restore frame pointers; it also
makes an extra register available in many functions. It also makes debugging impossible on some machines (the Motorola 68000 used in TI calculators is
such a case).
-foptimize-sibling-calls
Optimize sibling and tail recursive calls.
-fno-inline
Don't pay attention to the inline keyword. Normally this option is used to keep the compiler from expanding any functions inline. Note that if you are not
optimizing, no functions can be expanded inline.
-finline-functions
Integrate all simple functions into their callers. The compiler heuristically decides which functions are simple enough to be worth integrating in this way.
If all calls to a given function are integrated, and the function is declared static, then the function is normally not output as assembler code in its own
right.
-finline-limit=n
By default, gcc limits the size of functions that can be inlined. This flag allows the control of this limit for functions that are explicitly marked as inline
(i.e., marked with the inline keyword). n is the size of functions that can be inlined in number of pseudo instructions (not counting parameter handling).
The default value of n is 600. Increasing this value can result in more inlined code at the cost of compilation time and memory consumption. Decreasing
usually makes the compilation faster and less code will be inlined (which presumably means slower programs). This option is particularly useful for
programs that use inlining heavily.
Inlining is actually controlled by a number of parameters, which may be specified individually by using '--param name=value'. The '-finline-limit=n'
option sets some of these parameters as follows:
max-inline-insns
is set to n.
max-inline-insns-single
is set to n/2.
max-inline-insns-auto
is set to n/2.
min-inline-insns
is set to 130 or n/4, whichever is smaller.
max-inline-insns-rtl
is set to n.
Using '-finline-limit=600' thus results in the default settings for these parameters. See below for a documentation of the individual parameters
controlling inlining.
Note: pseudo instruction represents, in this particular context, an abstract measurement of function's size. In no way, it represents a count of assembly
instructions and as such its exact meaning might change from one release to an another.
-fkeep-inline-functions
Even if all calls to a given function are integrated, and the function is declared static, nevertheless output a separate run-time callable version of the
function. This switch does not affect extern inline functions.
-fkeep-static-consts
Emit variables declared static const when optimization isn't turned on, even if the variables aren't referenced.
GCC enables this option by default. If you want to force the compiler to check if the variable was referenced, regardless of whether or not optimization is
turned on, use the '-fno-keep-static-consts' option.
-fmerge-constants
Attempt to merge identical constants (string constants and floating point constants) across compilation units.
This option is the default for optimized compilation if the assembler and linker support it. Use '-fno-merge-constants' to inhibit this behavior.
-fmerge-all-constants
Attempt to merge identical constants and identical variables.
This option implies '-fmerge-constants'. In addition to '-fmerge-constants' this considers e.g. even constant initialized arrays or initialized constant
variables with integral or floating point types. C requires each non-automatic variable to have a distinct location, so using this option will result in non-
conforming behavior.
-fno-branch-count-reg
Do not use "decrement and branch" instructions on a count register, but instead generate a sequence of instructions that decrement a register, compare
it against zero, then branch based upon the result. This option is only meaningful on architectures that support such instructions, which include x86,
PowerPC, IA-64 and S/390.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 62 of 173
-fno-function-cse
Do not put function addresses in registers; make each instruction that calls a constant function contain the function's address explicitly.
This option results in less efficient code, but some strange hacks that alter the assembler output may be confused by the optimizations performed when
this option is not used.
-fno-zero-initialized-in-bss
If the target supports a BSS section (which is always the case for TIGCC now), GCC by default puts variables that are initialized to zero into BSS. This can
save space in the resulting code.
This option turns off this behavior because some programs explicitly rely on variables going to the data section. E.g., so that the resulting executable can
find the beginning of that section and/or make assumptions based on that.
-fstrength-reduce
Perform the optimizations of loop strength reduction and elimination of iteration variables.
-fthread-jumps
Perform optimizations where we check to see if a jump branches to a location where another comparison subsumed by the first is found. If so, the first
branch is redirected to either the destination of the second branch or a point immediately following it, depending on whether the condition is known to be
true or false.
-fcse-follow-jumps
In common subexpression elimination, scan through jump instructions when the target of the jump is not reached by any other path. For example, when
CSE encounters an if statement with an else clause, CSE will follow the jump when the condition tested is false.
-fcse-skip-blocks
This is similar to '-fcse-follow-jumps', but causes CSE to follow jumps which conditionally skip over blocks. When CSE encounters a simple if
statement with no else clause, '-fcse-skip-blocks' causes CSE to follow the jump around the body of the if.
-frerun-cse-after-loop
Re-run common subexpression elimination after loop optimizations have been performed.
-frerun-loop-opt
Run the loop optimizer twice.
-fgcse
Perform a global common subexpression elimination pass. This pass also performs global constant and copy propagation.
Note: When compiling a program using computed gotos, a GCC extension, you may get better runtime performance if you disable the global common
subexpression elimination pass by adding '-fno-gcse' to the command line.
-fgcse-lm
When '-fgcse-lm' is enabled, global common subexpression elimination will attempt to move loads which are only killed by stores into themselves. This
allows a loop containing a load/store sequence to be changed to a load outside the loop, and a copy/store within the loop.
-fgcse-sm
When '-fgcse-sm' is enabled, A store motion pass is run after global common subexpression elimination. This pass will attempt to move stores out of
loops. When used in conjunction with '-fgcse-lm', loops containing a load/store sequence can be changed to a load before the loop and a store after the
loop.
-floop-optimize
Perform loop optimizations: move constant expressions out of loops, simplify exit test conditions and optionally do strength-reduction and loop unrolling
as well.
-fcrossjumping
Perform cross-jumping transformation. This transformation unifies equivalent code and save code size. The resulting code may or may not perform better
than without cross-jumping.
-fif-conversion
Attempt to transform conditional jumps into branch-less equivalents. This include use of conditional moves, min, max, set flags and abs instructions, and
some tricks doable by standard arithmetics. The use of conditional execution on chips where it is available is controlled by if-conversion2.
-fif-conversion2
Use conditional execution (where available) to transform conditional jumps into branch-less equivalents.
-fdelete-null-pointer-checks
Use global dataflow analysis to identify and eliminate useless checks for null pointers. The compiler assumes that dereferencing a null pointer would have
halted the program. If a pointer is checked after it has already been dereferenced, it cannot be null.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 63 of 173
In some environments, this assumption is not true, and programs can safely dereference null pointers. Use '-fno-delete-null-pointer-checks' to disable
this optimization for programs which depend on that behavior.
-fexpensive-optimizations
Perform a number of minor optimizations that are relatively expensive.
-foptimize-register-move
-fregmove
Attempt to reassign register numbers in move instructions and as operands of other simple instructions in order to maximize the amount of register tying.
This is especially helpful on machines with two-operand instructions.
-fdelayed-branch
If supported for the target machine, attempt to reorder instructions to exploit instruction slots available after delayed branch instructions.
-fschedule-insns
If supported for the target machine, attempt to reorder instructions to eliminate execution stalls due to required data being unavailable. This helps
machines that have slow floating point or memory load instructions by allowing other instructions to be issued until the result of the load or floating point
instruction is required.
-fschedule-insns2
Similar to '-fschedule-insns', but requests an additional pass of instruction scheduling after register allocation has been done. This is especially useful
on machines with a relatively small number of registers and where memory load instructions take more than one cycle.
-fno-sched-interblock
Don't schedule instructions across basic blocks. This is normally enabled by default when scheduling before register allocation, i.e. with '-fschedule-
insns' or at '-O2' or higher.
-fno-sched-spec
Don't allow speculative motion of non-load instructions. This is normally enabled by default when scheduling before register allocation, i.e. with '-
fschedule-insns' or at '-O2' or higher.
-fsched-spec-load
Allow speculative motion of some load instructions. This only makes sense when scheduling before register allocation, i.e. with '-fschedule-insns' or at
'-O2' or higher.
-fsched-spec-load-dangerous
Allow speculative motion of more load instructions. This only makes sense when scheduling before register allocation, i.e. with '-fschedule-insns' or at '-
O2' or higher.
-fcaller-saves
Enable values to be allocated in registers that will be clobbered by function calls, by emitting extra instructions to save and restore the registers around
such calls. Such allocation is done only when it seems to result in better code than would otherwise be produced.
This option is always enabled by default on certain machines, usually those which have no call-preserved registers to use instead.
-fmove-all-movables
Forces all invariant computations in loops to be moved outside the loop.
-freduce-all-givs
Forces all general-induction variables in loops to be strength-reduced.
These options may generate better or worse code; results are highly dependent on the structure of loops within the source code.
These two options are intended to be removed someday, once they have helped determine the efficacy of various approaches to improving loop
optimizations.
-fno-peephole
-fno-peephole2
Disable any machine-specific peephole optimizations. The difference between '-fno-peephole' and '-fno-peephole2' is in how they are implemented in
the compiler; some targets use one, some use the other, a few use both.
-fbranch-probabilities
-fno-guess-branch-probability
Do not guess branch probabilities using a randomized model.
Sometimes gcc will opt to use a randomized model to guess branch probabilities, when none are available from either profiling feedback ('-fprofile-arcs')
or __builtin_expect. This means that different runs of the compiler on the same program may produce different object code.
In a hard real-time system, people don't want different runs of the compiler to produce code that has different behavior; minimizing non-determinism is
of paramount importance. This switch allows users to reduce non-determinism, possibly at the expense of inferior optimization.
-freorder-blocks
Reorder basic blocks in the compiled function in order to reduce number of taken branches and improve code locality.
-freorder-functions
Reorder basic blocks in the compiled function in order to reduce number of taken branches and improve code locality. This is implemented by using
special subsections text.hot for most frequently executed functions and text.unlikely for unlikely executed functions. Reordering is done by the linker
so object file format must support named sections and linker must place them in a reasonable way.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 64 of 173
Also profile feedback must be available in to make this option effective. See '-fprofile-arcs' for details.
-fstrict-aliasing
Allows the compiler to assume the strictest aliasing rules applicable to the language being compiled. For C, this activates optimizations based on the type
of expressions. In particular, an object of one type is assumed never to reside at the same address as an object of a different type, unless the types are
almost the same. For example, an unsigned int can alias an int, but not a void* or a double. A character type may alias any other type.
union a_union {
int i;
double d;
};
int f() {
a_union t;
t.d = 3.0;
return t.i;
}
The practice of reading from a different union member than the one most recently written to (called "type-punning") is common. Even with '-fstrict-
aliasing', type-punning is allowed, provided the memory is accessed through the union type. So, the code above will work as expected. However, this
code might not:
int f() {
a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
-falign-functions
-falign-functions=n
Align the start of functions to the next power-of-two greater than n, skipping up to n bytes. For instance, '-falign-functions=32' aligns functions to the
next 32-byte boundary, but '-falign-functions=24' would align to the next 32-byte boundary only if this can be done by skipping 23 bytes or less.
'-fno-align-functions' and '-falign-functions=1' are equivalent and mean that functions will not be aligned.
Some assemblers only support this flag when n is a power of two; in that case, it is rounded up.
-falign-labels
-falign-labels=n
Align all branch targets to a power-of-two boundary, skipping up to n bytes like '-falign-functions'. This option can easily make code slower, because it
must insert dummy operations for when the branch target is reached in the usual flow of the code.
If '-falign-loops' or '-falign-jumps' are applicable and are greater than this value, then their values are used instead.
If n is not specified, use a machine-dependent default which is very likely to be 1, meaning no alignment.
-falign-loops
-falign-loops=n
Align loops to a power-of-two boundary, skipping up to n bytes like '-falign-functions'. The hope is that the loop will be executed many times, which will
make up for any execution of the dummy operations.
-falign-jumps
-falign-jumps=n
Align branch targets to a power-of-two boundary, for branch targets where the targets can only be reached by jumping, skipping up to n bytes like '-
falign-functions'. In this case, no dummy operations need be executed.
-frename-registers
Attempt to avoid false dependencies in scheduled code by making use of registers left over after register allocation. This optimization will most benefit
processors with lots of registers. It can, however, make debugging impossible, since variables will no longer stay in a "home register".
-fno-cprop-registers
After register allocation and post-register allocation instruction splitting, we perform a copy-propagation pass to try to reduce scheduling dependencies
and occasionally eliminate the copy.
The following options control compiler behavior regarding floating point arithmetic. These options trade off between speed and correctness. All must be
specifically enabled.
-ffloat-store
Do not store floating point variables in registers, and inhibit other options that might change whether a floating point value is taken from a register or
memory.
This option prevents undesirable excess precision on machines such as the 68000 where the floating registers (of the 68881) keep more precision than a
double is supposed to have. Similarly for the x86 architecture. For most programs, the excess precision does only good, but a few programs rely on the
precise definition of IEEE floating point. Use '-ffloat-store' for such programs, after modifying them to store all pertinent intermediate computations into
variables.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 65 of 173
This option is probably useless in TIGCC, except as a workaround for floating point arithmetic errors.
-ffast-math
Sets '-fno-math-errno', '-funsafe-math-optimizations', '-fno-trapping-math', '-ffinite-math-only' and '-fno-signaling-nans'.
This option should never be turned on by any '-O' option since it can result in incorrect output for programs which depend on an exact implementation of
IEEE or ISO rules/specifications for math functions.
-fno-math-errno
Do not set ERRNO after calling math functions that are executed with a single instruction, e.g., sqrt. A program that relies on IEEE exceptions for math
error handling may want to use this flag for speed while maintaining IEEE arithmetic compatibility.
This option should never be turned on by any '-O' option since it can result in incorrect output for programs which depend on an exact implementation of
IEEE or ISO rules/specifications for math functions.
-funsafe-math-optimizations
Allow optimizations for floating-point arithmetic that (a) assume that arguments and results are valid and (b) may violate IEEE or ANSI standards. When
used at link-time, it may include libraries or startup files that change the default FPU control word or other similar optimizations.
This option should never be turned on by any '-O' option since it can result in incorrect output for programs which depend on an exact implementation of
IEEE or ISO rules/specifications for math functions.
-ffinite-math-only
Allow optimizations for floating-point arithmetic that assume that arguments and results are not NaNs or +-Infs.
This option should never be turned on by any '-O' option since it can result in incorrect output for programs which depend on an exact implementation of
IEEE or ISO rules/specifications.
-fno-trapping-math
Compile code assuming that floating-point operations cannot generate user-visible traps. These traps include division by zero, overflow, underflow,
inexact result and invalid operation. This option implies '-fno-signaling-nans'. Setting this option may allow faster code if one relies on "non-stop" IEEE
arithmetic, for example.
This option should never be turned on by any '-O' option since it can result in incorrect output for programs which depend on an exact implementation of
IEEE or ISO rules/specifications for math functions.
-fsignaling-nans
Compile code assuming that IEEE signaling NaNs may generate user-visible traps during floating-point operations. Setting this option disables
optimizations that may change the number of exceptions visible with signaling NaNs. This option implies '-ftrapping-math'.
This option is experimental and does not currently guarantee to disable all GCC optimizations that affect signaling NaN behavior.
-fsingle-precision-constant
Treat floating point constant as single precision constant instead of implicitly converting it to double precision constant.
The following options control optimizations that may improve performance, but are not enabled by any '-O' options. This section includes experimental options
that may produce broken code.
-fbranch-probabilities
After running a program compiled with '-fprofile-arcs' (see Options for Debugging Your Program or GCC), you can compile it a second time using '-
fbranch-probabilities', to improve optimizations based on the number of times each branch was taken. When the program compiled with '-fprofile-
arcs' exits, it saves arc execution counts to a file called sourcename.da for each source file. The information in this data file is very dependent on the
structure of the generated code, so you must use the same source code and the same optimization options for both compilations.
With '-fbranch-probabilities', GCC puts a REG_BR_PROB note on each JUMP_INSN and CALL_INSN. These can be used to improve optimization. Currently,
they are only used in one place: in reorg.c, instead of guessing which path a branch is mostly to take, the REG_BR_PROB values are used to exactly
determine which path is taken more often.
-fnew-ra
Use a graph coloring register allocator. Currently this option is meant for testing, so we are interested to hear about miscompilations with '-fnew-ra'.
-ftracer
Perform tail duplication to enlarge superblock size. This transformation simplifies the control flow of the function allowing other optimizations to do better
job.
-funroll-loops
Unroll loops whose number of iterations can be determined at compile time or upon entry to the loop. '-funroll-loops' implies both '-fstrength-reduce'
and '-frerun-cse-after-loop'. This option makes code larger, and may or may not make it run faster.
-funroll-all-loops
Unroll all loops, even if their number of iterations is uncertain when the loop is entered. This usually makes programs run more slowly. '-funroll-all-
loops' implies the same options as '-funroll-loops',
-fprefetch-loop-arrays
If supported by the target machine, generate instructions to prefetch memory to improve the performance of loops that access large arrays.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 66 of 173
-ffunction-sections
-fdata-sections
Place each function or data item into its own section in the output file if the target supports arbitrary sections. The name of the function or the name of
the data item determines the section's name in the output file.
Use these options on systems where the linker can perform optimizations to improve locality of reference in the instruction space. Most systems using the
ELF object format and SPARC processors running Solaris 2 have linkers with such optimizations. AIX may have these optimizations in the future.
Only use these options when there are significant benefits from doing so. When you specify these options, the assembler and linker will create larger
object and executable files and will also be slower. You will not be able to use gprof on all systems if you specify this option and you may have problems
with debugging if you specify both this option and '-g'.
-fssa
Perform optimizations in static single assignment form. Each function's flow graph is translated into SSA form, optimizations are performed, and the flow
graph is translated back from SSA form. Users should not specify this option, since it is not yet ready for production use.
-fssa-ccp
Perform Sparse Conditional Constant Propagation in SSA form. Requires '-fssa'. Like '-fssa', this is an experimental feature.
-fssa-dce
Perform aggressive dead-code elimination in SSA form. Requires '-fssa'. Like '-fssa', this is an experimental feature.
--param name=value
In some places, GCC uses various constants to control the amount of optimization that is done. For example, GCC will not inline functions that contain
more that a certain number of instructions. You can control some of these constants on the command-line using the '--param' option.
In each case, the value is an integer. The allowable choices for name are given in the following table:
max-crossjump-edges
The maximum number of incoming edges to consider for crossjumping. The algorithm used by '-fcrossjumping' is O(N^2) in the number of edges
incoming to each block. Increasing values mean more aggressive optimization, making the compile time increase with probably small improvement
in executable size.
max-delay-slot-insn-search
The maximum number of instructions to consider when looking for an instruction to fill a delay slot. If more than this arbitrary number of
instructions is searched, the time savings from filling the delay slot will be minimal so stop searching. Increasing values mean more aggressive
optimization, making the compile time increase with probably small improvement in executable run time.
max-delay-slot-live-search
When trying to fill delay slots, the maximum number of instructions to consider when searching for a block with valid live register information.
Increasing this arbitrarily chosen value means more aggressive optimization, increasing the compile time. This parameter should be removed when
the delay slot code is rewritten to maintain the control-flow graph.
max-gcse-memory
The approximate maximum amount of memory that will be allocated in order to perform the global common subexpression elimination optimization.
If more memory than specified is required, the optimization will not be done.
max-gcse-passes
The maximum number of passes of GCSE to run.
max-pending-list-length
The maximum number of pending dependencies scheduling will allow before flushing the current state and starting over. Large functions with few
branches or calls can create excessively large lists which needlessly consume memory and resources.
max-inline-insns-single
Several parameters control the tree inliner used in gcc. This number sets the maximum number of instructions (counted in gcc's internal
representation) in a single function that the tree inliner will consider for inlining. This only affects functions declared inline. The default value is 300.
max-inline-insns-auto
When you use '-finline-functions' (included in '-O3'), a lot of functions that would otherwise not be considered for inlining by the compiler will be
investigated. To those functions, a different (more restrictive) limit compared to functions declared inline can be applied. The default value is 300.
max-inline-insns
The tree inliner does decrease the allowable size for single functions to be inlined after we already inlined the number of instructions given here by
repeated inlining. This number should be a factor of two or more larger than the single function limit. Higher numbers result in better runtime
performance, but incur higher compile-time resource (CPU time, memory) requirements and result in larger binaries. Very high values are not
advisable, as too large binaries may adversely affect runtime performance. The default value is 600.
max-inline-slope
After exceeding the maximum number of inlined instructions by repeated inlining, a linear function is used to decrease the allowable size for single
functions. The slope of that function is the negative reciprocal of the number specified here. The default value is 32.
min-inline-insns
The repeated inlining is throttled more and more by the linear function after exceeding the limit. To avoid too much throttling, a minimum for this
function is specified here to allow repeated inlining for very small functions even when a lot of repeated inlining already has been done. The default
value is 130.
max-inline-insns-rtl
For languages that use the RTL inliner (this happens at a later stage than tree inlining), you can set the maximum allowable size (counted in RTL
instructions) for the RTL inliner with this parameter. The default value is 600.
max-unrolled-insns
The maximum number of instructions that a loop should have if that loop is unrolled, and if the loop is unrolled, it determines how many times the
loop code is unrolled.
hot-bb-count-fraction
Select fraction of the maximal count of repetitions of basic block in program given basic block needs to have to be considered hot.
hot-bb-frequency-fraction
Select fraction of the maximal frequency of executions of basic block in function given basic block needs to have to be considered hot
tracer-dynamic-coverage
tracer-dynamic-coverage-feedback
This value is used to limit superblock formation once the given percentage of executed instructions is covered. This limits unnecessary code size
expansion.
The 'tracer-dynamic-coverage-feedback' is used only when profile feedback is available. The real profiles (as opposed to statically estimated
ones) are much less balanced allowing the threshold to be larger value.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 67 of 173
tracer-max-code-growth
Stop tail duplication once code growth has reached given percentage. This is rather hokey argument, as most of the duplicates will be eliminated
later in cross jumping, so it may be set to much higher values than is the desired code growth.
tracer-min-branch-ratio
Stop reverse growth when the reverse probability of best edge is less than this threshold (in percent).
tracer-min-branch-ratio
tracer-min-branch-ratio-feedback
Stop forward growth if the best edge do have probability lower than this threshold.
Similarly to 'tracer-dynamic-coverage' two values are present, one for compilation for profile feedback and one for compilation without. The
value for compilation with profile feedback needs to be more conservative (higher) in order to make tracer effective.
ggc-min-expand
GCC uses a garbage collector to manage its own memory allocation. This parameter specifies the minimum percentage by which the garbage
collector's heap should be allowed to expand between collections. Tuning this may improve compilation speed; it has no effect on code generation.
The default is 30% + 70% * (RAM/1GB) with an upper bound of 100% when RAM >= 1GB. If getrlimit is available, the notion of "RAM" is the
smallest of actual RAM, RLIMIT_RSS, RLIMIT_DATA and RLIMIT_AS. If GCC is not able to calculate RAM on a particular platform, the lower bound of
30% is used. Setting this parameter and 'ggc-min-heapsize' to zero causes a full collection to occur at every opportunity. This is extremely slow,
but can be useful for debugging.
ggc-min-heapsize
Minimum size of the garbage collector's heap before it begins bothering to collect garbage. The first collection occurs after the heap expands by
'ggc-min-expand'% beyond 'ggc-min-heapsize'. Again, tuning this may improve compilation speed, and has no effect on code generation.
The default is RAM/8, with a lower bound of 4096 (four megabytes) and an upper bound of 131072 (128 megabytes). If getrlimit is available, the
notion of "RAM" is the smallest of actual RAM, RLIMIT_RSS, RLIMIT_DATA and RLIMIT_AS. If GCC is not able to calculate RAM on a particular
platform, the lower bound is used. Setting this parameter very large effectively disables garbage collection. Setting this parameter and 'ggc-min-
expand' to zero causes a full collection to occur at every opportunity.
These options control the C preprocessor, which is run on each C source file before actual compilation.
If you use the '-E' option, nothing is done except preprocessing. Some of these options make sense only together with '-E' because they cause the
preprocessor output to be unsuitable for actual compilation.
You can use '-Wp,option' to bypass the compiler driver and pass option directly through to the preprocessor. If option contains commas, it is split into multiple
options at the commas. However, many options are modified, translated or interpreted by the compiler driver before being passed to the preprocessor, and '-
Wp' forcibly bypasses this phase. The preprocessor's direct interface is undocumented and subject to change, so whenever possible you should avoid using '-
Wp' and let the driver handle the options instead.
-D name
Predefine name as a macro, with definition 1.
-D name=definition
Predefine name as a macro, with definition definition. There are no restrictions on the contents of definition, but if you are invoking the preprocessor from
a shell or shell-like program you may need to use the shell's quoting syntax to protect characters such as spaces that have a meaning in the shell syntax.
If you wish to define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any).
Parentheses are meaningful to most shells, so you will need to quote the option. With sh and csh, '-D'name(args...)=definition'' works.
'-D' and '-U' options are processed in the order they are given on the command line. All '-imacros file' and '-include file' options are processed after
all '-D' and '-U' options.
-U name
Cancel any previous definition of name, either built in or provided with a '-D' option.
-undef
Do not predefine any system-specific macros. The common predefined macros remain defined.
-I dir
Add the directory dir to the list of directories to be searched for header files. Directories named by '-I' are searched before the standard system include
directories. If the directory dir is a standard system include directory, the option is ignored to ensure that the default search order for system directories
and the special treatment of system headers are not defeated (see System Headers).
-o file
Write output to file. This is the same as specifying file as the second non-option argument to cpp. gcc has a different interpretation of a second non-
option argument, so you must use '-o' to specify the output file.
-Wall
Turns on all optional warnings which are desirable for normal code. At present this is '-Wcomment' and '-Wtrigraphs'. Note that many of the
preprocessor's warnings are on by default and have no options to control them.
-Wcomment
-Wcomments
Warn whenever a comment-start sequence /* appears in a /* comment, or whenever a backslash-newline appears in a // comment. (Both forms have
the same effect.)
-Wtrigraphs
Warn if any trigraphs are encountered. This option used to take effect only if '-trigraphs' was also specified, but now works independently. Warnings are
not given for trigraphs within comments, as they do not affect the meaning of the program.
-Wtraditional
Warn about certain constructs that behave differently in traditional and ISO C. Also warn about ISO C constructs that have no traditional C equivalent,
and problematic constructs which should be avoided. See Traditional Mode.
-Wimport
Warn the first time #import is used.
-Wundef
Warn whenever an identifier which is not a macro is encountered in an #if directive, outside of defined. Such identifiers are replaced with zero.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 68 of 173
-Wunused-macros
Warn about macros defined in the main file that are unused. A macro is used if it is expanded or tested for existence at least once. The preprocessor will
also warn if the macro has not been used at the time it is redefined or undefined.
Built-in macros, macros defined on the command line, and macros defined in include files are not warned about.
Note: If a macro is actually used, but only used in skipped conditional blocks, then CPP will report it as unused. To avoid the warning in such a case, you
might improve the scope of the macro's definition by, for example, moving it into the first skipped block. Alternatively, you could provide a dummy use
with something like:
-Wendif-labels
Warn whenever an #else or an #endif are followed by text. This usually happens in code of the form
#if FOO
...
#else FOO
...
#endif FOO
The second and third FOO should be in comments, but often are not in older programs. This warning is on by default.
-Werror
Make all warnings into hard errors. Source code which triggers warnings will be rejected.
-Wsystem-headers
Issue warnings for code in system headers. These are normally unhelpful in finding bugs in your own code, therefore suppressed. If you are responsible
for the system library, you may want to see them.
-w
Suppress all warnings, including those which GNU CPP issues by default.
-pedantic
Issue all the mandatory diagnostics listed in the C standard. Some of them are left out by default, since they trigger frequently on harmless code.
-pedantic-errors
Issue all the mandatory diagnostics, and make all mandatory diagnostics into errors. This includes mandatory diagnostics that GCC issues without '-
pedantic' but treats as warnings.
-M
Instead of outputting the result of preprocessing, output a rule suitable for make describing the dependencies of the main source file. The preprocessor
outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from '-
include' or '-imacros' command line options.
Unless specified explicitly (with '-MT' or '-MQ'), the object file name consists of the basename of the source file with any suffix replaced with object file
suffix. If there are many included files then the rule is split into several lines using \-newline. The rule has no commands.
This option does not suppress the preprocessor's debug output, such as '-dM'. To avoid mixing such debug output with the dependency rules you should
explicitly specify the dependency output file with '-MF', or use an environment variable like DEPENDENCIES_OUTPUT (see Environment Variables). Debug
output will still be sent to the regular output stream as normal.
Passing '-M' to the driver implies '-E', and suppresses warnings with an implicit '-w'.
-MM
Like '-M' but do not mention header files that are found in system header directories, nor header files that are included, directly or indirectly, from such a
header.
This implies that the choice of angle brackets or double quotes in an #include directive does not in itself determine whether that header will appear in '-
MM' dependency output. This is a slight change in semantics from GCC versions 3.0 and earlier.
-MF file
When used with '-M' or '-MM', specifies a file to write the dependencies to. If no '-MF' switch is given the preprocessor sends the rules to the same place
it would have sent preprocessed output.
When used with the driver options '-MD' or '-MMD', '-MF' overrides the default dependency output file.
-MG
In conjunction with an option such as '-M' requesting dependency generation, '-MG' assumes missing header files are generated files and adds them to
the dependency list without raising an error. The dependency filename is taken directly from the #include directive without prepending any path. '-MG'
also suppresses preprocessed output, as a missing header file renders this useless.
-MP
This option instructs CPP to add a phony target for each dependency other than the main file, causing each to depend on nothing. These dummy rules
work around errors make gives if you remove header files without updating the Makefile to match.
test.h:
-MT target
Change the target of the rule emitted by dependency generation. By default CPP takes the name of the main input file, including any path, deletes any file
suffix such as .c, and appends the platform's usual object suffix. The result is the target.
An '-MT' option will set the target to be exactly the string you specify. If you want multiple targets, you can specify them as a single argument to '-MT',
or use multiple '-MT' options.
$(objpfx)foo.o: foo.c
-MQ target
Same as '-MT', but it quotes any characters which are special to Make. The default target is automatically quoted, as if it were given with '-MQ'.
-MD
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 69 of 173
'-MD' is equivalent to '-M -MF file', except that '-E' is not implied. The driver determines file based on whether an '-o' option is given. If it is, the driver
uses its argument but with a suffix of .d, otherwise it take the basename of the input file and applies a .d suffix.
If '-MD' is used in conjunction with '-E', any '-o' switch is understood to specify the dependency output file, but if used without '-E', each '-o' is
understood to specify a target object file.
Since '-E' is not implied, '-MD' can be used to generate a dependency output file as a side-effect of the compilation process.
-MMD
Like '-MD' except mention only user header files, not system -header files.
-x c
-x c++
-x objective-c
-x assembler-with-cpp
Specify the source language: C, C++, Objective-C, or assembly. This has nothing to do with standards conformance or extensions; it merely selects which
base syntax to expect. If you give none of these options, cpp will deduce the language from the extension of the source file: .c, .cc, .m, or .S. Some
other common extensions for C++ and assembly are also recognized. If cpp does not recognize the extension, it will treat the file as C; this is the most
generic mode. Note that C++ and Objective-C are not supported in TIGCC.
Note: Previous versions of cpp accepted a '-lang' option which selected both the language and the standards conformance level. This option has been
removed, because it conflicts with the '-l' option.
-std=standard
-ansi
Specify the standard to which the code should conform. Currently CPP knows about C and C++ standards; others may be added in the future (although it
will not be important for TIGCC).
iso9899:1990
c89
The ISO C standard from 1990. c89 is the customary shorthand for this version of the standard.
iso9899:199409
The 1990 C standard, as amended in 1994.
iso9899:1999
c99
iso9899:199x
c9x
The revised ISO C standard, published in December 1999. Before publication, this was known as C9X.
gnu89
The 1990 C standard plus GNU extensions. This is the default.
gnu99
gnu9x
The 1999 C standard plus GNU extensions.
c++98
The 1998 ISO C++ standard plus amendments.
gnu++98
The same as '-std=c++98' plus GNU extensions. This is the default for C++ code.
-I-
Split the include path. Any directories specified with '-I' options before '-I-' are searched only for headers requested with #include "file"; they are not
searched for #include <file>. If additional directories are specified with '-I' options after the '-I-', those directories are searched for all #include
directives.
In addition, '-I-' inhibits the use of the directory of the current file directory as the first search directory for #include "file".
-nostdinc
Do not search the standard system directories for header files. Only the directories you have specified with '-I' options (and the directory of the current
file, if appropriate) are searched.
-nostdinc++
Do not search for header files in the C++-specific standard directories, but do still search the other standard directories (not applicable to TIGCC, because
it does not support C++).
-include file
Process file as if #include "file" appeared as the first line of the primary source file. However, the first directory searched for file is the preprocessor's
working directory instead of the directory containing the main source file. If not found there, it is searched for in the remainder of the #include "..."
search chain as normal.
If multiple '-include' options are given, the files are included in the order they appear on the command line.
-imacros file
Exactly like '-include', except that any output produced by scanning file is thrown away. Macros it defines remain defined. This allows you to acquire all
the macros from a header without also processing its declarations.
All files specified by '-imacros' are processed before all files specified by '-include'.
-idirafter dir
Search dir for header files, but do it after all directories specified with '-I' and the standard system directories have been exhausted. dir is treated as a
system include directory.
-iprefix prefix
Specify prefix as the prefix for subsequent '-iwithprefix' options. If the prefix represents a directory, you should include the final /.
-iwithprefix dir
-iwithprefixbefore dir
Append dir to the prefix specified previously with '-iprefix', and add the resulting directory to the include search path. '-iwithprefixbefore' puts it in the
same place '-I' would; '-iwithprefix' puts it where '-idirafter' would.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 70 of 173
-isystem dir
Search dir for header files, after all directories specified by '-I' but before the standard system directories. Mark it as a system directory, so that it gets
the same special treatment as is applied to the standard system directories. See System Headers.
-fpreprocessed
Indicate to the preprocessor that the input file has already been preprocessed. This suppresses things like macro expansion, trigraph conversion, escaped
newline splicing, and processing of most directives. The preprocessor still recognizes and removes comments, so that you can pass a file preprocessed
with '-C' to the compiler without problems. In this mode the integrated preprocessor is little more than a tokenizer for the front ends.
'-fpreprocessed' is implicit if the input file has one of the extensions .i, .ii or .mi. These are the extensions that GCC uses for preprocessed files
created by '-save-temps'.
-ftabstop=width
Set the distance between tab stops. This helps the preprocessor report correct column numbers in warnings or errors, even if tabs appear on the line. If
the value is less than 1 or greater than 100, the option is ignored. The default is 8.
-fno-show-column
Do not print column numbers in diagnostics. This may be necessary if diagnostics are being scanned by a program that does not understand the column
numbers, such as dejagnu.
-A predicate=answer
Make an assertion with the predicate predicate and answer answer. This form is preferred to the older form '-A predicate(answer)', which is still
supported, because it does not use shell special characters. See Assertions.
-A -predicate=answer
Cancel an assertion with the predicate predicate and answer answer.
-dCHARS
CHARS is a sequence of one or more of the following characters, and must not be preceded by a space. Other characters are interpreted by the compiler
proper, or reserved for future versions of GCC, and so are silently ignored. If you specify characters whose behavior conflicts, the result is undefined.
M
Instead of the normal output, generate a list of #define directives for all the macros defined during the execution of the preprocessor, including
predefined macros. This gives you a way of finding out what is predefined in your version of the preprocessor. Assuming you have no file foo.h, the
command
D
Like M except in two respects: it does not include the predefined macros, and it outputs both the #define directives and the result of preprocessing.
Both kinds of output go to the standard output file.
N
Like D, but emit only the macro names, not their expansions.
I
Output #include directives in addition to the result of preprocessing.
-P
Inhibit generation of linemarkers in the output from the preprocessor. This might be useful when running the preprocessor on something that is not C
code, and will be sent to a program which might be confused by the linemarkers. See Preprocessor Output.
-C
Do not discard comments. All comments are passed through to the output file, except for comments in processed directives, which are deleted along with
the directive.
You should be prepared for side effects when using '-C'; it causes the preprocessor to treat comments as tokens in their own right. For example,
comments appearing at the start of what would be a directive line have the effect of turning that line into an ordinary source line, since the first token on
the line is no longer a #.
-CC
Do not discard comments, including during macro expansion. This is like '-C', except that comments contained within macros are also passed through to
the output file where the macro is expanded.
In addition to the side-effects of the '-C' option, the '-CC' option causes all C++-style comments inside a macro to be converted to C-style comments.
This is to prevent later use of that macro from inadvertently commenting out the remainder of the source line.
-gcc
Define the macros __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__. These are defined automatically when you use gcc -E; you can turn
them off in that case with '-no-gcc'.
-traditional-cpp
Try to imitate the behavior of old-fashioned C preprocessors, as opposed to ISO C preprocessors. See Traditional Mode.
-trigraphs
Process trigraph sequences. See Initial processing. These are three-character sequences, all starting with ??, that are defined by ISO C to stand for single
characters. For example, ??/ stands for \, so '??/n' is a character constant for a newline. By default, GCC ignores trigraphs, but in standard-conforming
modes it converts them. See the '-std' and '-ansi' options.
Trigraph: ??( ??) ??< ??> ??= ??/ ??' ??! ??-
Replacement: [ ] { } # \ ^ | ~
-remap
Enable special code to work around file systems which only permit very short file names, such as MS-DOS.
--help
--target-help
Print text describing all the command line options instead of preprocessing anything.
-v
Verbose mode. Print out GNU CPP's version number at the beginning of execution, and report the final form of the include path.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 71 of 173
-H
Print the name of each header file used, in addition to other normal activities. Each name is indented to show how deep in the #include stack it is.
-version
--version
Print out GNU CPP's version number. With one dash, proceed to preprocess as normal. With two dashes, exit immediately.
You can pass options to the GNU assembler, to the A68k assembler, and to the GNU linker.
However, this is only possible this way if you are using the command line compiler. In the IDE, you have to use the appropriate edit boxes in the project
options.
-Wa,option
Pass option as an option to the GNU assembler. If option contains commas, it is split into multiple options at the commas.
-WA,option
Pass option as an option to the A68k assembler. If option contains commas, it is split into multiple options at the commas. This is a TIGCC-only switch.
-Wl,option
Pass option as an option to the GNU linker. If option contains commas, it is split into multiple options at the commas.
These options specify directories to search for header files, for libraries and for parts of the compiler:
-Idir
Add the directory dir to the head of the list of directories to be searched for header files. This can be used to override a system header file, substituting
your own version, since these directories are searched before the system header file directories. However, you should not use this option to add
directories that contain vendor-supplied system header files (use '-isystem' for that). If you use more than one '-I' option, the directories are scanned in
left-to-right order; the standard system directories come after.
If a standard system include directory, or a directory specified with '-isystem', is also specified with '-I', the '-I' option will be ignored. The directory will
still be searched but as a system directory at its normal position in the system include chain. This is to ensure that GCC's procedure to fix buggy system
headers and the ordering for the include_next directive are not inadvertently changed. If you really need to change the search order for system
directories, use the '-nostdinc' and/or '-isystem' options.
-I-
Any directories you specify with '-I' options before the '-I-' option are searched only for the case of #include "file"; they are not searched for
#include <file>.
If additional directories are specified with '-I' options after the '-I-', these directories are searched for all #include directives. (Ordinarily all '-I'
directories are used this way.)
In addition, the '-I-' option inhibits the use of the current directory (where the current input file came from) as the first search directory for
#include "file". There is no way to override this effect of '-I-'. With '-I.' you can specify searching the directory which was current when the compiler
was invoked. That is not exactly the same as what the preprocessor does by default, but it is often satisfactory.
'-I-' does not inhibit the use of the standard system directories for header files. Thus, '-I-' and '-nostdinc' are independent.
-Ldir
Add directory dir to the list of directories to be searched for '-l'.
-Bprefix
This option specifies where to find the executables, libraries, include files, and data files of the compiler itself.
The compiler will check to see if the path provided by the '-B' refers to a directory, and if necessary it will add a directory separator character at the end
of the path.
Another way to specify a prefix much like the '-B' prefix is to use the environment variable GCC_EXEC_PREFIX. See Environment Variables.
-specs=file
Process file after the compiler reads in the standard specs file, in order to override the defaults that the gcc driver program uses when determining what
switches to pass to the individual programs. This does not work in TIGCC.
gcc is a driver program. It performs its job by invoking a sequence of other programs to do the work of compiling, assembling and linking. GCC interprets its
command-line parameters and uses these to deduce which programs it should invoke, and which command-line options it ought to place on their command
lines. This behavior is controlled by spec strings. In most cases there is one spec string for each program that GCC can invoke, but a few programs have
multiple spec strings to control their behavior. The spec strings built into GCC can be overridden by using the '-specs=' command-line switch to specify a spec
file.
Spec files are plaintext files that are used to construct spec strings. They consist of a sequence of directives separated by blank lines.
Since gcc only performs a small part of the tasks in TIGCC, spec strings are more or less irrelevant. For details on specs, see the original documentation on the
net.
The GCC compiler used in TIGCC is configured for just one target family: the Motorola M680x0 (M68k) family. In the TI-89, TI-92+, and V200 calculators, an
MC68000 processor is used, therefore TIGCC creates code for such a processor by default. However, switches specifying the processor model, such as '-
m68020', still exist, although they are not useful. However, there are also options that control the code that is generated specifically for TI calculators; they
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 72 of 173
-mno-bss
Output all uninitialized global or static variables as normal data with zero content. Note that this leads to different semantics if the program is not
compressed or archived: The variables will keep their values even after program termination, instead of being initialized to zero every time the program is
run. For a better alternative, see MERGE_BSS.
-mlong
Consider type int to be 32 bits wide, like long int. The '-mshort' option is enabled by default in TIGCC; the negative is actually '-mnoshort', but '-
mno-short' and '-mlong' have been added as aliases. Constants such as INT_MAX are set to the appropriate values, and __INT_SHORT__ will be defined
if short integers are used (i.e. if this switch is not used). This option may be useful if you need to port code from a system which uses long integers.
-mno-tios
Again, this is the negative form of a switch called '-mtios', which changes the convention for returning pointers from functions, and which also implies '-
fcall-used-d2'. This is necessary to make GCC work with the TIOS calling conventions, therefore '-mno-tios' may only be used if no interaction with the
operating system is required. Since library calls also use the TIOS calling convention, they cannot be used either; you should disable linking against
tigcc.a. Only use this option if you know exactly what you are doing.
-mmlink
Assume that uninitialized global variables can be handled smartly through BSS blocks even in kernel-less mode.
-mpcrel
Use the pc-relative addressing mode of the 68000 directly, instead of using a global offset table (also known as the relocation table). Therefore, this
option produces position-independent code.
-mregparm[=regcount]
Use register passing for all user-defined functions. regcount data registers plus regcount address registers are used to pass arguments to functions. If
regcount is not specified, a default value of 2 is used. You should not specify a value higher than 6, or 5 if you use OPTIMIZE_ROM_CALLS. Note that you
have to be careful with callback functions if you use this switch, although you will be warned about incompatiblities.
-mbitfield
Use bit-field instructions.
-malign-int
Aligns int, long, long long, float, double, and long double variables on a 32-bit boundary.
-mno-strict-align
-mstrict-align
Do not or do assume that unaligned memory references will be handled by the system.
-mno-merge-sections
Do not merge the .text and .data sections, as TIGCC normally does (to save space used by relocation).
-mmerge-to-data
When merging sections, merge to .data rather than to .text.
-mrodata-to-text
When not merging sections, put read-only data into .text rather than .data.
These machine-independent options control the interface conventions used in code generation.
Most of them have both positive and negative forms; the negative form of '-ffoo' would be '-fno-foo'. In the table below, only one of the forms is listed: the
one which is not the default. You can figure out the other form by either removing 'no-' or adding it.
-fbounds-check
For front-ends that support it, generate additional code to check that indices used to access arrays are within the declared range. This is currently only
supported by the Java and Fortran 77 front-ends, where this option defaults to true and false respectively.
-ftrapv
This option generates traps for signed overflow on addition, subtraction, multiplication operations.
-fexceptions
Enable exception handling. Generates extra code needed to propagate exceptions. In principle, you may need to enable this option when compiling C code
that needs to interoperate properly with exception handlers, but this is useless in TIGCC, as the TIOS uses its own exception handling mechanism (see
error.h).
-fnon-call-exceptions
Generate code that allows trapping instructions to throw exceptions. Probably useless in TIGCC.
-funwind-tables
Similar to '-fexceptions', except that it will just generate any needed static data, but will not affect the generated code in any other way. Probably
useless in TIGCC.
-fasynchronous-unwind-tables
Generate unwind table in dwarf2 format, if supported by target machine. The table is exact at each instruction boundary, so it can be used for stack
unwinding from asynchronous events (such as debugger or garbage collector).
-fpcc-struct-return
Return "short" struct and union values in memory like longer ones, rather than in registers. This convention is less efficient, but it has the advantage of
allowing intercallability between GCC-compiled files and files compiled with other compilers, particularly the Portable C Compiler (pcc).
The precise convention for returning structures in memory depends on the target configuration macros.
Short structures and unions are those whose size and alignment match that of some integer type.
Warning: code compiled with the '-fpcc-struct-return' switch is not binary compatible with code compiled with the '-freg-struct-return' switch. Use it
to conform to a non-default application binary interface.
-freg-struct-return
Return struct and union values in registers when possible. This is more efficient for small structures than '-fpcc-struct-return'.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 73 of 173
Warning: code compiled with the '-freg-struct-return' switch is not binary compatible with code compiled with the '-fpcc-struct-return' switch. Use it
to conform to a non-default application binary interface.
-fshort-enums
Allocate to an enum type only as many bytes as it needs for the declared range of possible values. Specifically, the enum type will be equivalent to the
smallest integer type which has enough room.
Warning: the '-fshort-enums' switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to
conform to a non-default application binary interface.
-fshort-double
Use the same size for double as for float. This is always true in TIGCC, regardless of this switch.
Warning: the '-fshort-double' switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to
conform to a non-default application binary interface.
-fshort-wchar
Override the underlying type for wchar_t to be short unsigned int instead of the default for the target. This option is useful for building programs to
run under WINE.
Warning: the '-fshort-wchar' switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to
conform to a non-default application binary interface.
-fshared-data
Requests that the data and non-const variables of this compilation be shared data rather than private data. The distinction makes sense only on certain
operating systems, where shared data is shared between processes running the same program, while private data exists in one copy per process.
-fno-common
Allocate even uninitialized global variables in the data section of the object file, rather than generating them as common blocks. This has the effect that if
the same variable is declared (without extern) in two different compilations, you will get an error when you link them. The only reason this might be
useful is if you wish to verify that the program will work on other systems which always work this way. Currently, TIGCC does not support this option,
since it needs common symbols to communicate with the linker.
-fno-ident
Ignore the #ident directive.
-fno-gnu-linker
Do not output global initializations in the form used by the GNU linker Useless in TIGCC, because global initializations are not implemented.
-finhibit-size-directive
Don't output a .size assembler directive, or anything else that would cause trouble if the function is split in the middle, and the two halves are placed at
locations far apart in memory. This option is used when compiling crtstuff.c; you should not need to use it for anything else.
-fverbose-asm
Put extra commentary information in the generated assembly code to make it more readable. This option is generally only of use to those who actually
need to read the generated assembly code (perhaps while debugging the compiler itself).
'-fno-verbose-asm', the default, causes the extra information to be omitted and is useful when comparing two assembler files.
-fvolatile
Consider all memory references through pointers to be volatile.
-fvolatile-global
Consider all memory references to extern and global data items to be volatile. GCC does not consider static data items to be volatile because of this
switch.
-fvolatile-static
Consider all memory references to static data to be volatile.
-fpic
Generate position-independent code (PIC) suitable for use in a shared library. However, it requires special support of the operating system (like dynamic
loaders, etc.). So forget it with the TIOS; maybe some future ASM shells will support this. At the moment, forget this nice option.
-fPIC
If supported for the target machine, emit position-independent code, suitable for dynamic linking and avoiding any limit on the size of the global offset
table.
-ffixed-reg
Treat the register named reg as a fixed register; generated code should never refer to it (except perhaps as a stack pointer, frame pointer or in some
other fixed role).
This flag does not have a negative form, because it specifies a three-way choice.
-fcall-used-reg
Treat the register named reg as an allocable register that is clobbered by function calls. It may be allocated for temporaries or variables that do not live
across a call. Functions compiled this way will not save and restore the register reg.
It is an error to used this flag with the frame pointer or stack pointer. Use of this flag for other registers that have fixed pervasive roles in the machine's
execution model will produce disastrous results.
This flag does not have a negative form, because it specifies a three-way choice.
-fcall-saved-reg
Treat the register named reg as an allocable register saved by functions. It may be allocated even for temporaries or variables that live across a call.
Functions compiled this way will save and restore the register reg if they use it.
It is an error to used this flag with the frame pointer or stack pointer. Use of this flag for other registers that have fixed pervasive roles in the machine's
execution model will produce disastrous results.
A different sort of disaster will result from the use of this flag for a register in which function values may be returned.
This flag does not have a negative form, because it specifies a three-way choice.
-freg-relative-reg
Refer to all labels only in relation to the register specified in reg. This can make the code somewhat smaller, but you should use this option with care as it
is not fully supported. This option is implemented only in TIGCC.
-fpack-struct
Pack all structure members together without holes.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 74 of 173
Warning: the '-fpack-struct' switch causes GCC to generate code that is not binary compatible with code generated without that switch. Additionally, it
makes the code suboptimal. Use it to conform to a non-default application binary interface.
-finstrument-functions
Generate instrumentation calls for entry and exit to functions. Just after function entry and just before function exit, the following profiling functions will
be called with the address of the current function and its call site. (On some platforms, __builtin_return_address does not work beyond the current
function, so the call site information may not be available to the profiling functions otherwise.)
The first argument is the address of the start of the current function, which may be looked up exactly in the symbol table.
This instrumentation is also done for functions expanded inline in other functions. The profiling calls will indicate where, conceptually, the inline function is
entered and exited. This means that addressable versions of such functions must be available. If all your uses of a function are expanded inline, this may
mean an additional expansion of code size. If you use extern inline in your C code, an addressable version of such functions must be provided. (This is
normally the case anyways, but if you get lucky and the optimizer always expands the functions inline, you might have gotten away without providing
static copies.)
A function may be given the attribute no_instrument_function, in which case this instrumentation will not be done. This can be used, for example, for
the profiling functions listed above, high-priority interrupt routines, and any functions from which the profiling functions cannot safely be called (perhaps
signal handlers, if the profiling routines generate output or allocate memory).
-fstack-check
Generate code to verify that you do not go beyond the boundary of the stack. As this requires support from the operating system, it probably does not
work in TIGCC.
-fstack-limit-register=reg
-fstack-limit-symbol=sym
-fno-stack-limit
Generate code to ensure that the stack does not grow beyond a certain value, either the value of a register or the address of a symbol. If the stack would
grow beyond the value, a signal is raised. For most targets, the signal is raised before the stack overruns the boundary, so it is possible to catch the
signal without taking special precautions.
For instance, if the stack starts at absolute address 0x80000000 and grows downwards, you can use the flags '-fstack-limit-symbol=__stack_limit'
and '-Wl,--defsym,__stack_limit=0x7ffe0000' to enforce a stack limit of 128KB. Note that this may only work with the GNU linker.
-fargument-alias
-fargument-noalias
-fargument-noalias-global
Specify the possible relationships among parameters and between parameters and global data.
'-fargument-alias' specifies that arguments (parameters) may alias each other and may alias global storage.
'-fargument-noalias' specifies that arguments do not alias each other, but may alias global storage.
'-fargument-noalias-global' specifies that arguments do not alias each other and do not alias global storage.
Each language will automatically use whatever option is required by the language standard. You should not need to use these options yourself.
-fleading-underscore
This option and its counterpart, '-fno-leading-underscore', forcibly change the way C symbols are represented in the object file. One use is to help link
with legacy assembly code.
Warning: the '-fleading-underscore' switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it
to conform to a non-default application binary interface.
-ftls-model=model
Alter the thread-local storage model to be used. The model argument should be one of global-dynamic, local-dynamic, initial-exec or local-exec.
The default without '-fpic' is initial-exec; with '-fpic' the default is global-dynamic.
This section describes several environment variables that affect how GCC operates. Some of them work by specifying directories or prefixes to use when
searching for various kinds of files. Some are used to specify other aspects of the compilation environment.
Note that you can also specify places to search using options such as '-B', '-I' and '-L' (see Options for Directory Search).
LANG
LC_CTYPE
LC_MESSAGES
LC_ALL
These environment variables control the way that GCC uses localization information that allow GCC to work with different national conventions. GCC
inspects the locale categories LC_CTYPE and LC_MESSAGES if it has been configured to do so. These locale categories can be set to any value supported by
your installation. A typical value is en_UK for English in the United Kingdom.
The LC_CTYPE environment variable specifies character classification. GCC uses it to determine the character boundaries in a string; this is needed for
some multibyte encodings that contain quote and escape characters that would otherwise be interpreted as a string end or escape.
The LC_MESSAGES environment variable specifies the language to use in diagnostic messages.
If the LC_ALL environment variable is set, it overrides the value of LC_CTYPE and LC_MESSAGES; otherwise, LC_CTYPE and LC_MESSAGES default to the
value of the LANG environment variable. If none of these variables are set, GCC defaults to traditional C English behavior.
TMPDIR
If TMPDIR is set, it specifies the directory to use for temporary files. GCC uses temporary files to hold the output of one stage of compilation which is to be
used as input to the next stage: for example, the output of the preprocessor, which is the input to the compiler proper.
GCC_EXEC_PREFIX
If GCC_EXEC_PREFIX is set, it specifies a prefix to use in the names of the subprograms executed by the compiler. No slash is added when this prefix is
combined with the name of a subprogram, but you can specify a prefix that ends with a slash if you wish.
If GCC_EXEC_PREFIX is not set, GCC will attempt to figure out an appropriate prefix to use based on the pathname it was invoked with.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 75 of 173
If GCC cannot find the subprogram using the specified prefix, it tries looking in the usual places for the subprogram.
The default value of GCC_EXEC_PREFIX is prefix/lib/gcc-lib/ where prefix is the value of prefix when you ran the configure script.
Other prefixes specified with '-B' take precedence over this prefix.
In addition, the prefix is used in an unusual way in finding the directories to search for header files. For each of the standard directories whose name
normally begins with /usr/local/lib/gcc-lib (more precisely, with the value of GCC_INCLUDE_DIR), GCC tries replacing that beginning with the
specified prefix to produce an alternate directory name. Thus, with '-Bfoo/', GCC will search foo/bar where it would normally
search /usr/local/lib/bar. These alternate directories are searched first; the standard directories come next.
COMPILER_PATH
The value of COMPILER_PATH is a colon-separated list of directories, much like PATH. GCC tries the directories thus specified when searching for
subprograms, if it can't find the subprograms using GCC_EXEC_PREFIX.
LIBRARY_PATH
The value of LIBRARY_PATH is a colon-separated list of directories, much like PATH. When configured as a native compiler (which TIGCC is not), GCC tries
the directories thus specified when searching for special linker files, if it can't find them using GCC_EXEC_PREFIX. Linking using GCC also uses these
directories when searching for ordinary libraries for the '-l' option (but directories specified with '-L' come first).
LANG
This variable is used to pass locale information to the compiler. One way in which this information is used is to determine the character set to be used
when character literals, string literals and comments are parsed. When the compiler is configured to allow multibyte characters, the following values for
LANG are recognized:
C-JIS
Recognize JIS characters.
C-SJIS
Recognize SJIS characters.
C-EUCJP
Recognize EUCJP characters.
If LANG is not defined, or if it has some other value, then the compiler will use mblen and mbtowc as defined by the default locale to recognize and
translate multibyte characters.
CPATH
C_INCLUDE_PATH
Each variable's value is a list of directories separated by a special character, much like PATH, in which to look for header files. The special character,
PATH_SEPARATOR, is target-dependent and determined at GCC build time. For Windows-based targets it is a semicolon, and for almost all other targets it
is a colon.
CPATH specifies a list of directories to be searched as if specified with '-I', but after any paths given with '-I' options on the command line.
C_INCLUDE_PATH specifies a list of directories to be searched as if specified with '-isystem', but after any paths given with '-isystem' options on the
command line.
In all these variables, an empty element instructs the compiler to search its current working directory. Empty elements can appear at the beginning or
end of a path. For instance, if the value of CPATH is :/special/include, that has the same effect as -I. -I/special/include.
DEPENDENCIES_OUTPUT
If this variable is set, its value specifies how to output dependencies for Make based on the non-system header files processed by the compiler. System
header files are ignored in the dependency output.
The value of DEPENDENCIES_OUTPUT can be just a file name, in which case the Make rules are written to that file, guessing the target name from the
source file name. Or the value can have the form file target, in which case the rules are written to file file using target as the target name.
In other words, this environment variable is equivalent to combining the options '-MM' and '-MF' (see Options Controlling the Preprocessor), with an
optional '-MT' switch, too.
SUNPRO_DEPENDENCIES
This variable is the same as DEPENDENCIES_OUTPUT (see above), except that system header files are not ignored, so it implies '-M' rather than '-MM' (see
Options Controlling the Preprocessor). However, the dependence on the main input file is omitted.
History
Copyright © 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Copyright © 2000, 2001, 2002 Zeljko Juric, Sebastian Reichelt, Kevin Kofler
This part of the documentation is a modified version of the GNU CPP Manual. Therefore it is licensed under the GNU Free Documentation License.
The C preprocessor is a macro processor that is used automatically by the C compiler to transform your program before actual compilation. It is called a macro
processor because it allows you to define macros, which are brief abbreviations for longer constructs.
Preprocessor Overview
Header Files
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 76 of 173
Macros
Conditionals
Pragmas
Other Directives
User-defined Diagnostics
Line Control
Preprocessor Output
C Preprocessor Command-Line Options
Traditional Mode
Implementation Details
History
GNU General Public License
GNU Free Documentation License
Funding Free Software
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version
published by the Free Software Foundation. A copy of the license is included in the section entitled "GNU Free Documentation License".
This manual contains no Invariant Sections. The Front-Cover Texts are (a) (see below), and the Back-Cover Texts are (b) (see below).
A GNU Manual
You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development.
Preprocessor Overview
The C preprocessor, often known as cpp, is a macro processor that is used automatically by the C compiler to transform your program before compilation. It is
called a macro processor because it allows you to define macros, which are brief abbreviations for longer constructs.
The C preprocessor is intended to be used only with C, C++, and Objective-C source code. In the past, it has been abused as a general text processor. It will
choke on input which does not obey C's lexical rules. For example, apostrophes will be interpreted as the beginning of character constants, and cause errors.
Also, you cannot rely on it preserving characteristics of the input which are not significant to C-family languages. If a Makefile is preprocessed, all the hard tabs
will be removed, and the Makefile will not work.
Having said that, you can often get away with using cpp on things which are not C. Other Algol-ish programming languages are often safe (Pascal, Ada, etc.) So
is assembly, with caution. '-traditional-cpp' mode preserves more white space, and is otherwise more permissive. Many of the problems can be avoided by
writing C or C++ style comments instead of native language comments, and keeping macros simple.
Wherever possible, you should use a preprocessor geared to the language you are writing in. Modern versions of the GNU assembler have macro facilities. Most
high level programming languages have their own conditional compilation and inclusion mechanism. If all else fails, try a true general text processor, such as
GNU M4.
C preprocessors vary in some details. This manual discusses the GNU C preprocessor, which provides a small superset of the features of ISO Standard C. In its
default mode, the GNU C preprocessor does not do a few things required by the standard. These are features which are rarely, if ever, used, and may cause
surprising changes to the meaning of a program which does not expect them. To get strict ISO Standard C, you should use the '-std=c89' or '-std=c99'
options, depending on which version of the standard you want. To get all the mandatory diagnostics, you must also use '-pedantic'. See Invocation.
This manual describes the behavior of the ISO preprocessor. To minimize gratuitous differences, where the ISO preprocessor's behavior does not conflict with
traditional semantics, the traditional preprocessor should behave the same way. The various differences that do exist are detailed in the section Traditional
Mode.
For clarity, unless noted otherwise, references to CPP in this manual refer to GNU CPP.
Initial processing
Tokenization
The preprocessing language
Initial processing
The preprocessor performs a series of textual transformations on its input. These happen before all other processing. Conceptually, they happen in a rigid order,
and the entire file is run through each transformation before the next one begins. CPP actually does them all at once, for performance reasons. These
transformations correspond roughly to the first three "phases of translation" described in the C standard.
1. The input file is read into memory and broken into lines.
CPP expects its input to be a text file, that is, an unstructured stream of ASCII characters, with some characters indicating the end of a line of text.
Extended ASCII character sets, such as ISO Latin-1 or Unicode encoded in UTF-8, are also acceptable. Character sets that are not strict supersets of
seven-bit ASCII will not work. We plan to add complete support for international character sets in a future release.
Different systems use different conventions to indicate the end of a line. GCC accepts the ASCII control sequences LF, CR LF, CR, and LF CR as end-of-
line markers. The first three are the canonical sequences used by Unix, DOS and VMS, and the classic Mac OS (before OSX) respectively. You may
therefore safely copy source code written on any of those systems to a different one and use it without conversion. (GCC may lose track of the current
line number if a file doesn't consistently use one convention, as sometimes happens when it is edited on computers with different conventions that share
a network file system.) LF CR is included because it has been reported as an end-of-line marker under exotic conditions.
If the last line of any input file lacks an end-of-line marker, the end of the file is considered to implicitly supply one. The C standard says that this
condition provokes undefined behavior, so GCC will emit a warning message.
2. If trigraphs are enabled, they are replaced by their corresponding single characters. By default GCC ignores trigraphs, but if you request a strictly
conforming mode with the '-std' option, or you specify the '-trigraphs' option, then it converts them.
These are nine three-character sequences, all starting with ??, that are defined by ISO C to stand for single characters. They permit obsolete systems
that lack some of C's punctuation to use C. For example, ??/ stands for \, so '??/n' is a character constant for a newline.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 77 of 173
Trigraphs are not popular and many compilers implement them incorrectly. Portable code should not rely on trigraphs being either converted or ignored.
If you use the '-Wall' or '-Wtrigraphs' options, GCC will warn you when a trigraph would change the meaning of your program if it were converted.
In a string constant, you can prevent a sequence of question marks from being confused with a trigraph by inserting a backslash between the question
marks. "(??\?)" is the string (???), not (?]. Traditional C compilers do not recognize this idiom.
Trigraph: ??( ??) ??< ??> ??= ??/ ??' ??! ??-
Replacement: [ ] { } # \ ^ | ~
A continued line is a line which ends with a backslash, \. The backslash is removed and the following line is joined with the current one. No space is
inserted, so you may split a line anywhere, even in the middle of a word. (It is generally more readable to split lines only at white space.)
If there is white space between a backslash and the end of a line, that is still a continued line. However, as this is usually the result of an editing mistake,
and many compilers will not accept it as a continued line, GCC will warn you about it.
There are two kinds of comments. Block comments begin with /* and continue until the next */. Block comments do not nest:
Line comments begin with // and continue to the end of the current line. Line comments do not nest either, but it does not matter, because they would
end in the same place anyway.
/* block comment
// contains line comment
yet more comment
*/ outside comment
But beware of commenting out one end of a block comment with a line comment.
Comments are not recognized within string literals. "/* blah */" is the string constant /* blah */, not an empty string.
Line comments are not in the 1989 edition of the C standard, but they are recognized by GCC as an extension. In C++ and in the 1999 edition of the C
standard, they are an official part of the language.
Since these transformations happen before all other processing, you can split a line mechanically with backslash-newline anywhere. You can comment out the
end of a line. You can continue a line comment onto the next line with backslash-newline. You can even split /*, */, and // onto multiple lines with backslash-
newline. For example:
/\
*
*/ # /*
*/ defi\
ne FO\
O 10\
20
is equivalent to #define FOO 1020. All these tricks are extremely confusing and should not be used in code intended to be readable.
There is no way to prevent a backslash at the end of a line from being interpreted as a backslash-newline. This cannot affect any correct program, however.
Tokenization
After the textual transformations are finished, the input file is converted into a sequence of preprocessing tokens. These mostly correspond to the syntactic
tokens used by the C compiler, but there are a few differences. White space separates tokens; it is not itself a token of any kind. Tokens do not have to be
separated by white space, but it is often necessary to avoid ambiguities.
When faced with a sequence of characters that has more than one possible tokenization, the preprocessor is greedy. It always makes each token, starting from
the left, as big as possible before moving on to the next token. For instance, a+++++b is interpreted as a ++ ++ + b, not as a ++ + ++ b, even though the
latter tokenization could be part of a valid C program and the former could not.
Once the input file is broken into tokens, the token boundaries never change, except when the ## preprocessing operator is used to paste tokens together. See
Concatenation. For example,
The compiler does not re-tokenize the preprocessor's output. Each preprocessing token becomes one compiler token.
Preprocessing tokens fall into five broad classes: identifiers, preprocessing numbers, string literals, punctuators, and other. An identifier is the same as an
identifier in C: any sequence of letters, digits, or underscores, which begins with a letter or underscore. Keywords of C have no significance to the preprocessor;
they are ordinary identifiers. You can define a macro whose name is a keyword, for instance. The only identifier which can be considered a preprocessing
keyword is defined.
In the 1999 C standard, identifiers may contain letters which are not part of the "basic source character set," at the implementation's discretion (such as
accented Latin letters, Greek letters, or Chinese ideograms). This may be done with an extended character set, or the \u and \U escape sequences. GCC does
not presently implement either feature in the preprocessor or the compiler.
As an extension, GCC treats $ as a letter. This is for compatibility with some systems, such as VMS, where $ is commonly used in system-defined function and
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 78 of 173
object names. $ is not a letter in strictly conforming mode, or if you specify the '-$' option. See Invocation.
A preprocessing number has a rather bizarre definition. The category includes all the normal integer and floating point constants one expects of C, but also a
number of other things one might not initially recognize as a number. Formally, preprocessing numbers begin with an optional period, a required decimal digit,
and then continue with any sequence of letters, digits, underscores, periods, and exponents. Exponents are the two-character sequences e+, e-, E+, E-, p+, p-,
P+, and P-. (The exponents that begin with p or P are new to C99. They are used for hexadecimal floating-point constants.)
The purpose of this unusual definition is to isolate the preprocessor from the full complexity of numeric constants. It does not have to distinguish between
lexically valid and invalid floating-point numbers, which is complicated. The definition also permits you to split an identifier at any position and get exactly two
tokens, which can then be pasted back together with the ## operator.
It's possible for preprocessing numbers to cause programs to be misinterpreted. For example, 0xE+12 is a preprocessing number which does not translate to
any valid numeric constant, therefore a syntax error. It does not mean 0xE + 12, which is what you might have intended.
String literals are string constants, character constants, and header file names (the argument of #include). The C standard uses the term string literal to refer
only to what we are calling string constants. String constants and character constants are straightforward: "..." or '...'. In either case embedded quotes
should be escaped with a backslash: '\'' is the character constant for '. There is no limit on the length of a character constant, but the value of a character
constant that contains more than one character is implementation-defined. See Implementation Details.
Header file names either look like string constants, "...", or are written with angle brackets instead, <...>. In either case, backslash is an ordinary character.
There is no way to escape the closing quote or angle bracket. The preprocessor looks for the header file in different places depending on which form you use.
See Include Operation.
In standard C, no string literal may extend past the end of a line. GNU CPP accepts multi-line string constants, but not multi-line character constants or header
file names. To write standards-compliant code, you may use continued lines instead, or string constant concatenation. See Differences from previous versions.
Punctuators are all the usual bits of punctuation which are meaningful to C and C++. All but three of the punctuation characters in ASCII are C punctuators.
The exceptions are @, $, and '. In addition, all the two- and three-character operators are punctuators. There are also six digraphs, which the C++ standard
calls alternative tokens, which are merely alternate ways to spell other punctuators. This is a second attempt to work around missing punctuation in obsolete
systems. It has no negative side effects, unlike trigraphs, but does not cover as much ground. The digraphs and their corresponding normal punctuators are:
Any other single character is considered "other." It is passed on to the preprocessor's output unmolested. The C compiler will almost certainly reject source
code containing "other" tokens. In ASCII, the only other characters are @, $, ', and control characters other than NUL (all bits zero). (Note that $ is normally
considered a letter.) All characters with the high bit set (numeric range 0x7F--0xFF) are also "other" in the present implementation. This will change when
proper support for international character sets is added to GCC.
NUL is a special case because of the high probability that its appearance is accidental, and because it may be invisible to the user (many terminals do not
display NUL at all). Within comments, NULs are silently ignored, just as any other character would be. In running text, NUL is considered white space. For
example, these two directives have the same meaning.
#define X^@1
#define X 1
(where ^@ is ASCII NUL). Within string or character constants, NULs are preserved. In the latter two cases the preprocessor emits a warning message.
After tokenization, the stream of tokens may simply be passed straight to the compiler's parser. However, if it contains any operations in the preprocessing
language, it will be transformed first. This stage corresponds roughly to the standard's "translation phase 4" and is what most people think of as the
preprocessor's job.
The preprocessing language consists of directives to be executed and macros to be expanded. Its primary capabilities are:
Inclusion of header files. These are files of declarations that can be substituted into your program.
Macro expansion. You can define macros, which are abbreviations for arbitrary fragments of C code. The preprocessor will replace the macros with their
definitions throughout the program. Some macros are automatically defined for you.
Conditional compilation. You can include or exclude parts of the program according to various conditions.
Line control. If you use a program to combine or rearrange source files into an intermediate file which is then compiled, you can use line control to inform
the compiler where each source line originally came from.
Diagnostics. You can detect problems at compile time and issue errors or warnings.
Except for expansion of predefined macros, all these operations are triggered with preprocessing directives. Preprocessing directives are lines in your program
that start with #. Whitespace is allowed before and after the #. The # is followed by an identifier, the directive name. It specifies the operation to perform.
Directives are commonly referred to as #name where name is the directive name. For example, #define is the directive that defines a macro.
The # which begins a directive cannot come from a macro expansion. Also, the directive name is not macro expanded. Thus, if foo is defined as a macro
expanding to define, that does not make #foo a valid preprocessing directive.
The set of valid directive names is fixed. Programs cannot define new preprocessing directives.
Some directives require arguments; these make up the rest of the directive line and must be separated from the directive name by whitespace. For example,
#define must be followed by a macro name and the intended expansion of the macro.
A preprocessing directive cannot cover more than one line. The line may, however, be continued with backslash-newline, or by a block comment which extends
past the end of the line. In either case, when the directive is processed, the continuations have already been merged with the first line to make one long line.
Header Files
A header file is a file containing C declarations and macro definitions (see Macros) to be shared between several source files. You request the use of a header
file in your program by including it, with the C preprocessing directive #include.
System header files declare the interfaces to parts of the operating system. You include them in your program to supply the definitions and declarations
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 79 of 173
Your own header files contain declarations for interfaces between the source files of your program. Each time you have a group of related declarations
and macro definitions all or most of which are needed in several different source files, it is a good idea to create a header file for them.
Including a header file produces the same results as copying the header file into each source file that needs it. Such copying would be time-consuming and
error-prone. With a header file, the related declarations appear in only one place. If they need to be changed, they can be changed in one place, and programs
that include the header file will automatically use the new version when next recompiled. The header file eliminates the labor of finding and changing all the
copies as well as the risk that a failure to find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with .h. It is most portable to use only letters, digits, dashes, and underscores in header file
names, and at most one dot.
Include Syntax
Include Operation
Once-Only Headers
Computed Includes
Wrapper Headers
System Headers
Include Syntax
Both user and system header files are included using the preprocessing directive #include. It has two variants:
#include <file>
This variant is used for system header files. It searches for a file named file in a standard list of system directories. You can prepend directories to this list
with the '-I' option (see Invocation).
#include "file"
This variant is used for header files of your own program. It searches for a file named file first in the directory containing the current file, then in the same
directories used for <file>.
The argument of #include, whether delimited with quote marks or angle brackets, behaves like a string constant in that comments are not recognized, and
macro names are not expanded. Thus, #include <x/*y> specifies inclusion of a system header file named x/*y.
However, if backslashes occur within file, they are considered ordinary text characters, not escape characters. None of the character escape sequences
appropriate to string constants in C are processed. Thus, #include "x\n\\y" specifies a filename containing three backslashes. (Some systems interpret \ as a
pathname separator. All of these also interpret / the same way. It is most portable to use only /.)
It is an error if there is anything (other than comments) on the line after the file name.
Include Operation
The #include directive works by directing the C preprocessor to scan the specified file as input before continuing with the rest of the current file. The output
from the preprocessor contains the output already generated, followed by the output resulting from the included file, followed by the output that comes from
the text after the #include directive. For example, if you have a header file header.h as follows,
and a main program called program.c that uses the header file, like this,
int x;
#include "header.h"
int
main (void)
{
puts (test ());
}
the compiler will see the same token stream as it would if program.c read
int x;
char *test (void);
int
main (void)
{
puts (test ());
}
Included files are not limited to declarations and macro definitions; those are merely the typical uses. Any fragment of a C program can be included from
another file. The include file could even contain the beginning of a statement that is concluded in the containing file, or the end of a statement that was started
in the including file. However, an included file must consist of complete tokens. Comments and string literals which have not been closed by the end of an
included file are invalid. For error recovery, they are considered to end at the end of the file.
To avoid confusion, it is best if header files contain only complete syntactic units - function declarations or definitions, type declarations, etc.
The line following the #include directive is always treated as a separate line by the C preprocessor, even if the included file lacks a final newline.
Once-Only Headers
If a header file happens to be included twice, the compiler will process its contents twice. This is very likely to cause an error, e.g. when the compiler sees the
same structure definition twice. Even if it does not, it will certainly waste time.
The standard way to prevent this is to enclose the entire real contents of the file in a conditional, like this:
/* File foo. */
#ifndef FILE_FOO_SEEN
#define FILE_FOO_SEEN
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 80 of 173
#endif /* !FILE_FOO_SEEN */
This construct is commonly known as a wrapper #ifndef. When the header is included again, the conditional will be false, because FILE_FOO_SEEN is defined.
The preprocessor will skip over the entire contents of the file, and the compiler will not see it twice.
CPP optimizes even further. It remembers when a header file has a wrapper #ifndef. If a subsequent #include specifies that header, and the macro in the
#ifndef is still defined, it does not bother to rescan the file at all.
You can put comments outside the wrapper. They will not interfere with this optimization.
The macro FILE_FOO_SEEN is called the controlling macro or guard macro. In a user header file, the macro name should not begin with _. In a system header
file, it should begin with __ to avoid conflicts with user programs. In any kind of header file, the macro name should contain the name of the file and some
additional text, to avoid conflicts with other header files.
Computed Includes
Sometimes it is necessary to select one of several different header files to be included into your program. They might specify configuration parameters to be
used on different sorts of operating systems, for instance. You could do this with a series of conditionals,
#if SYSTEM_1
# include "system_1.h"
#elif SYSTEM_2
# include "system_2.h"
#elif SYSTEM_3
...
#endif
That rapidly becomes tedious. Instead, the preprocessor offers the ability to use a macro for the header name. This is called a computed include. Instead of
writing a header name as the direct argument of #include, you simply put a macro name there instead:
SYSTEM_H will be expanded, and the preprocessor will look for system_1.h as if the #include had been written that way originally. SYSTEM_H could be defined
by your Makefile with a '-D' option.
You must be careful when you define the macro. #define saves tokens, not text. The preprocessor has no way of knowing that the macro will be used as the
argument of #include, so it generates ordinary tokens, not a header name. This is unlikely to cause problems if you use double-quote includes, which are close
enough to string constants. If you use angle brackets, however, you may have trouble.
The syntax of a computed include is actually a bit more general than the above. If the first non-whitespace character after #include is not " or <, then the
entire line is macro-expanded like running text would be.
If the line expands to a single string constant, the contents of that string constant are the file to be included. CPP does not re-examine the string for embedded
quotes, but neither does it process backslash escapes in the string. Therefore
looks for a file named a\"b. CPP searches for the file according to the rules for double-quoted includes.
If the line expands to a token stream beginning with a < token and including a > token, then the tokens between the < and the first > are combined to form the
filename to be included. Any whitespace between tokens is reduced to a single space; then any space after the initial < is retained, but a trailing space before
the closing > is ignored. CPP searches for the file according to the rules for angle-bracket includes.
In either case, if there are any tokens on the line after the file name, an error occurs and the directive is not processed. It is also an error if the result of
expansion does not match either of the two expected forms.
These rules are implementation-defined behavior according to the C standard. To minimize the risk of different compilers interpreting your computed includes
differently, we recommend you use only a single object-like macro which expands to a string constant. This will also minimize confusion for people reading your
program.
Wrapper Headers
Sometimes it is necessary to adjust the contents of a system-provided header file without editing it directly (although it is not very likely that this feature will
ever be used in TIGCC). GCC's fixincludes operation does this, for example. One way to do that would be to create a new header file with the same name and
insert it in the search path before the original header. That works fine as long as you're willing to replace the old header entirely. But what if you want to refer
to the old header from the new one?
You cannot simply include the old header with #include. That will start from the beginning, and find your new header again. If your header is not protected
from multiple inclusion (see Once-Only Headers), it will recurse infinitely and cause a fatal error.
#include "/usr/include/old-header.h"
This works, but is not clean; should the system headers ever move, you would have to edit the new headers to match.
There is no way to solve this problem within the C standard, but you can use the GNU extension #include_next. It means, "Include the next file with this
name." This directive works like #include except in searching for the specified file: it starts searching the list of header file directories after the directory in
which the current file was found.
Suppose you specify '-I /usr/local/include', and the list of directories to search also includes /usr/include; and suppose both directories contain signal.h.
Ordinary #include <signal.h> finds the file under /usr/local/include. If that file contains #include_next <signal.h>, it starts searching after that
directory, and finds the file in /usr/include.
#include_next does not distinguish between <file> and "file" inclusion, nor does it check that the file you specify has the same name as the current file. It
simply looks for the file named, starting with the directory in the search path after the one where the current file was found.
The use of #include_next can lead to great confusion. We recommend it be used only when there is no other alternative. In particular, it should not be used in
the headers belonging to a specific program; it should be used only to make global corrections along the lines of fixincludes.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 81 of 173
System Headers
The header files declaring interfaces to the operating system and runtime libraries often cannot be written in strictly conforming C. Therefore, GCC gives code
found in system headers special treatment. All warnings, other than those generated by #warning (see Diagnostics), are suppressed while GCC is processing a
system header. Macros defined in a system header are immune to a few warnings wherever they are expanded. This immunity is granted on an ad-hoc basis,
when we find that a warning generates lots of false positives because of code in macros defined in system headers.
Normally, only the headers found in specific directories are considered system headers. These directories are determined when GCC is compiled. There are,
however, two ways to make normal headers into system headers.
The '-isystem' command line option adds its argument to the list of directories to search for headers, just like '-I'. Any headers found in that directory will be
considered system headers.
All directories named by '-isystem' are searched after all directories named by '-I', no matter what their order was on the command line. If the same directory
is named by both '-I' and '-isystem', the '-I' option is ignored. GCC provides an informative message when this occurs if '-v' is used.
There is also a directive, #pragma GCC system_header, which tells GCC to consider the rest of the current include file a system header, no matter where it was
found. Code that comes before the #pragma in the file will not be affected. #pragma GCC system_header has no effect in the primary source file.
On very old systems, some of the pre-defined system header directories get even more special treatment. GNU C++ considers code in headers found in those
directories to be surrounded by an extern "C" block. There is no way to request this behavior with a #pragma, or from the command line.
Macros
A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. There are two kinds of
macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble
function calls.
You may define any valid identifier as a macro, even if it is a C keyword. The preprocessor does not know anything about keywords. This can be useful if you
wish to hide a keyword such as const from an older compiler that does not understand it. However, the preprocessor operator defined can never be defined as
a macro.
Object-like Macros
Function-like Macros
Stringification
Concatenation
Undefining and Redefining Macros
Predefined Macros
Directives Within Macro Arguments
Macro Pitfalls
Object-like Macros
Macros Next
An object-like macro is a simple identifier which will be replaced by a code fragment. It is called object-like because it looks like a data object in code that uses
it. They are most commonly used to give symbolic names to numeric constants.
You create macros with the #define directive. #define is followed by the name of the macro and then the token sequence it should be an abbreviation for,
which is variously referred to as the macro's body, expansion or replacement list. For example,
defines a macro named BUFFER_SIZE as an abbreviation for the token 1024. If somewhere after this #define directive there comes a C statement of the form
then the C preprocessor will recognize and expand the macro BUFFER_SIZE. The C compiler will see the same tokens as it would if you had written
By convention, macro names are written in upper case. Programs are easier to read when it is possible to tell at a glance which names are macros.
The macro's body ends at the end of the #define line. You may continue the definition onto multiple lines, if necessary, using backslash-newline. When the
macro is expanded, however, it will all come out on one line. For example,
#define NUMBERS 1, \
2, \
3
int x[] = { NUMBERS };
expands to int x[] = { 1, 2, 3 };
The most common visible consequence of this is surprising line numbers in error messages.
There is no restriction on what can go in a macro body provided it decomposes into valid preprocessing tokens. Parentheses need not balance, and the body
need not resemble valid C code. (If it does not, you may get error messages from the C compiler when you use the macro.)
The C preprocessor scans your program sequentially. Macro definitions take effect at the place you write them. Therefore, the following input to the C
preprocessor
foo = X;
#define X 4
bar = X;
produces
foo = X;
bar = 4;
When the preprocessor expands a macro name, the macro's expansion replaces the macro invocation, then the expansion is examined for more macros to
expand. For example,
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 82 of 173
TABLESIZE is expanded first to produce BUFSIZE, then that macro is expanded to produce the final result, 1024.
Notice that BUFSIZE was not defined when TABLESIZE was defined. The #define for TABLESIZE uses exactly the expansion you specify - in this case, BUFSIZE -
and does not check to see whether it too contains macro names. Only when you use TABLESIZE is the result of its expansion scanned for more macro names.
This makes a difference if you change the definition of BUFSIZE at some point in the source file. TABLESIZE, defined as shown, will always expand using the
definition of BUFSIZE that is currently in effect:
If the expansion of a macro contains its own name, either directly or via intermediate macros, it is not expanded again when the expansion is examined for
more macros. This prevents infinite recursion. See Self-Referential Macros for the precise details.
Function-like Macros
You can also define macros whose use looks like a function call. These are called function-like macros. To define a function-like macro, you use the same
#define directive, but you put a pair of parentheses immediately after the macro name. For example,
A function-like macro is only expanded if its name appears with a pair of parentheses after it. If you write just the name, it is left alone. This can be useful
when you have a function and a macro of the same name, and you wish to use the function sometimes.
Here the call to foo() will use the macro, but the function pointer will get the address of the real function. If the macro were to be expanded, it would cause a
syntax error.
If you put spaces between the macro name and the parentheses in the macro definition, that does not define a function-like macro, it defines an object-like
macro whose expansion happens to begin with a pair of parentheses.
The first two pairs of parentheses in this expansion come from the macro. The third is the pair that was originally after the macro invocation. Since lang_init
is an object-like macro, it does not consume those parentheses.
Macro Arguments
Variadic Macros
Macro Arguments
Function-like macros can take arguments, just like true functions. To define a macro that uses arguments, you insert parameters between the pair of
parentheses in the macro definition that make the macro function-like. The parameters must be valid C identifiers, separated by commas and optionally
whitespace.
To invoke a macro that takes arguments, you write the name of the macro followed by a list of actual arguments in parentheses, separated by commas. The
invocation of the macro need not be restricted to a single logical line - it can cross as many lines in the source file as you wish. The number of arguments you
give must match the number of parameters in the macro definition. When the macro is expanded, each use of a parameter in its body is replaced by the tokens
of the corresponding argument. (You need not use all of the parameters in the macro body.)
As an example, here is a macro that computes the minimum of two numeric values, as it is defined in many C programs, and some uses.
(In this small example you can already see several of the dangers of macro arguments. See Macro Pitfalls for detailed explanations.)
Leading and trailing whitespace in each argument is dropped, and all whitespace between the tokens of an argument is reduced to a single space. Parentheses
within each argument must balance; a comma within such parentheses does not end the argument. However, there is no requirement for square brackets or
braces to balance, and they do not prevent a comma from separating arguments. Thus,
passes two arguments to macro: array[x = y and x + 1]. If you want to supply array[x = y, x + 1] as an argument, you can write it as array
[(x = y, x + 1)], which is equivalent C code.
All arguments to a macro are completely macro-expanded before they are substituted into the macro body. After substitution, the complete text is scanned
again for macros to expand, including the arguments. This rule may seem strange, but it is carefully designed so you need not worry about whether any
function call is actually a macro invocation. You can run into trouble if you try to be too clever, though. See Argument Prescan for detailed discussion.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 83 of 173
and then to
(Line breaks shown here for clarity would not actually be generated.)
You can leave macro arguments empty; this is not an error to the preprocessor (but many macros will then expand to invalid code). You cannot leave out
arguments entirely; if a macro takes two arguments, there must be exactly one comma at the top level of its argument list. Here are some silly examples using
min:
Whitespace is not a preprocessing token, so if a macro foo takes one argument, foo () and foo ( ) both supply it an empty argument. Previous GNU
preprocessor implementations and documentation were incorrect on this point, insisting that a function-like macro that takes a single argument be passed a
space if an empty argument was required.
Macro parameters appearing inside string literals are not replaced by their corresponding actual arguments.
Variadic Macros
A macro can be declared to accept a variable number of arguments much as a function can. The syntax for defining the macro is similar to that of a function.
Here is an example:
This kind of macro is called variadic. When the macro is invoked, all the tokens in its argument list after the last named argument (this macro has none),
including any commas, become the variable argument. This sequence of tokens replaces the identifier __VA_ARGS__ in the macro body wherever it appears.
Thus, we have this expansion:
The variable argument is completely macro-expanded before it is inserted into the macro expansion, just like an ordinary argument. You may use the # and ##
operators to stringify the variable argument or to paste its leading or trailing token with another token. (But see below for an important special case for ##.)
If your macro is complicated, you may want a more descriptive name for the variable argument than __VA_ARGS__. CPP permits this, as an extension. You may
write an argument name immediately before the ...; that name is used for the variable argument. The lprintf macro above could be written
using this extension. You cannot use __VA_ARGS__ and this extension in the same macro.
You can have named arguments as well as variable arguments in a variadic macro. We could define lprintf like this, instead:
This formulation looks more descriptive, but unfortunately it is less flexible: you must now supply at least one argument after the format string. In standard C,
you cannot omit the comma separating the named argument from the variable arguments. Furthermore, if you leave the variable argument empty, you will get
a syntax error, because there will be an extra comma after the format string.
lprintf ("success!\n", );
--> fprintf (log, "success!\n", );
GNU CPP has a pair of extensions which deal with this problem. First, you are allowed to leave the variable argument out entirely:
lprintf ("success!\n");
--> fprintf (log, "success!\n", );
Second, the ## token paste operator has a special meaning when placed between a comma and a variable argument. If you write
and the variable argument is left out when the lprintf macro is used, then the comma before the ## will be deleted. This does not happen if you pass an
empty argument, nor does it happen if the token preceding ## is anything other than a comma.
lprintf ("success!\n")
--> fprintf (log, "success!\n");
The above explanation is ambiguous about the case where the only macro parameter is a variable arguments parameter, as it is meaningless to try to
distinguish whether no argument at all is an empty argument or a missing argument. In this case the C99 standard is clear that the comma must remain,
however the existing GCC extension used to swallow the comma. So CPP retains the comma when conforming to a specific C standard, and drops it otherwise.
C99 mandates that the only place the identifier __VA_ARGS__ can appear is in the replacement list of a variadic macro. It may not be used as a macro name,
macro argument name, or within a different type of macro. It may also be forbidden in open text; the standard is ambiguous. We recommend you avoid using it
except for its defined purpose.
Variadic macros are a new feature in C99. GNU CPP has supported them for a long time, but only with a named variable argument (args..., not ... and
__VA_ARGS__). If you are concerned with portability to previous versions of GCC, you should use only named variable arguments. On the other hand, if you are
concerned with portability to other conforming implementations of C99, you should use only __VA_ARGS__.
Previous versions of CPP implemented the comma-deletion extension much more generally. We have restricted it in this release to minimize the differences
from C99. To get the same effect with both this and previous versions of GCC, the token preceding the special ## must be a comma, and there must be white
space between that comma and whatever comes immediately before it:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 84 of 173
Stringification
Sometimes you may want to convert a macro argument into a string constant. Parameters are not replaced inside string constants, but you can use the #
preprocessing operator instead. When a macro parameter is used with a leading #, the preprocessor replaces it with the literal text of the actual argument,
converted to a string constant. Unlike normal parameter replacement, the argument is not macro-expanded first. This is called stringification.
There is no way to combine an argument with surrounding text and stringify it all together. Instead, you can write a series of adjacent string constants and
stringified arguments. The preprocessor will replace the stringified arguments with string constants. The C compiler will then combine all the adjacent string
constants into one long string.
#define WARN_IF(EXP) \
do { if (EXP) \
fprintf (stderr, "Warning: " #EXP "\n"); } \
while (0)
WARN_IF (x == 0);
expands to do { if (x == 0)
fprintf (stderr, "Warning: " "x == 0" "\n"); } while (0);
The argument for EXP is substituted once, as-is, into the if statement, and once, stringified, into the argument to fprintf. If x were a macro, it would be
expanded in the if statement, but not in the string.
The do and while (0) are a kludge to make it possible to write WARN_IF (arg);, which the resemblance of WARN_IF to a function would make C programmers
want to do; see Swallowing the Semicolon.
Stringification in C involves more than putting double-quote characters around the fragment. The preprocessor backslash-escapes the quotes surrounding
embedded string constants, and all backslashes within string and character constants, in order to get a valid C string constant with the proper contents. Thus,
stringifying p = "foo\n"; results in "p = \"foo\\n\";". However, backslashes that are not inside string or character constants are not duplicated: \n by itself
stringifies to "\n".
All leading and trailing whitespace in text being stringified is ignored. Any sequence of whitespace in the middle of the text is converted to a single space in the
stringified result. Comments are replaced by whitespace long before stringification happens, so they never appear in stringified text.
If you want to stringify the result of expansion of a macro argument, you have to use two levels of macros.
s is stringified when it is used in str, so it is not macro-expanded first. But s is an ordinary argument to xstr, so it is completely macro-expanded before xstr
itself is expanded (see Argument Prescan). Therefore, by the time str gets to its argument, it has already been macro-expanded.
Concatenation
It is often useful to merge two tokens into one while expanding macros. This is called token pasting or token concatenation. The ## preprocessing operator
performs token pasting. When a macro is expanded, the two tokens on either side of each ## operator are combined into a single token, which then replaces
the ## and the two original tokens in the macro expansion. Usually both will be identifiers, or one will be an identifier and the other a preprocessing number.
When pasted, they make a longer identifier. This isn't the only valid case. It is also possible to concatenate two numbers (or a number and a name, such as 1.5
and e3) into a number. Also, multi-character operators such as += can be formed by token pasting.
However, two tokens that don't together form a valid token cannot be pasted together. For example, you cannot concatenate x with + in either order. If you try,
the preprocessor issues a warning and emits the two tokens. Whether it puts white space between the tokens is undefined. It is common to find unnecessary
uses of ## in complex macros. If you get this warning, it is likely that you can simply remove the ##.
Both the tokens combined by ## could come from the macro body, but you could just as well write them as one token in the first place. Token pasting is most
useful when one or both of the tokens comes from a macro argument. If either of the tokens next to an ## is a parameter name, it is replaced by its actual
argument before ## executes. As with stringification, the actual argument is not macro-expanded first. If the argument is empty, that ## has no effect.
Keep in mind that the C preprocessor converts comments to whitespace before macros are even considered. Therefore, you cannot create a comment by
concatenating / and *. You can put as much whitespace between ## and its operands as you like, including comments, and you can put comments in
arguments that will be concatenated. However, it is an error if ## appears at either end of a macro body.
Consider a C program that interprets named commands. There probably needs to be a table of commands, perhaps an array of structures declared as follows:
struct command
{
char *name;
void (*function) (void);
};
It would be cleaner not to have to give each command name twice, once in the string constant and once in the function name. A macro which takes the name
of a command as an argument can make this unnecessary. The string constant can be created with stringification, and the function name by concatenating the
argument with _command. Here is how it is done:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 85 of 173
...
};
If a macro ceases to be useful, it may be undefined with the #undef directive. #undef takes a single argument, the name of the macro to undefine. You use the
bare macro name, even if the macro is function-like. It is an error if anything appears on the line after the macro name. #undef has no effect if the name is not
a macro.
#define FOO 4
x = FOO; expands to x = 4;
#undef FOO
x = FOO; expands to x = FOO;
Once a macro has been undefined, that identifier may be redefined as a macro by a subsequent #define directive. The new definition need not have any
resemblance to the old definition.
However, if an identifier which is currently a macro is redefined, then the new definition must be effectively the same as the old one. Two macro definitions are
effectively the same if:
Whitespace appears in the same places in both. It need not be exactly the same amount of whitespace, though. Remember that comments count as
whitespace.
#define FOUR (2 + 2)
#define FOUR (2 + 2)
#define FOUR (2 /* two */ + 2)
#define FOUR (2 + 2)
#define FOUR ( 2+2 )
#define FOUR (2 * 2)
#define FOUR(score,and,seven,years,ago) (2 + 2)
If a macro is redefined with a definition that is not effectively the same as the old one, the preprocessor issues a warning and changes the macro to use the
new definition. If the new definition is effectively the same, the redefinition is silently ignored. This allows, for instance, two different headers to define a
common macro. The preprocessor will only complain if the definitions do not match.
Predefined Macros
Several object-like macros are predefined; you use them without supplying their definitions. They fall into three classes: standard, common, and system-
specific.
In C++, there is a fourth category, the named operators. They act like predefined macros, but you cannot undefine them.
The standard predefined macros are specified by the C and/or C++ language standards, so they are available with all compilers that implement those
standards. Older compilers may not provide all of them. Their names all start with double underscores.
__FILE__
__LINE__
__DATE__
__TIME__
__STDC__
__STDC_VERSION__
__STDC_HOSTED__
__FILE__
This macro expands to the name of the current input file, in the form of a C string constant. This is the path by which the preprocessor opened the file, not the
short name specified in #include or as the input file name argument. For example, "/usr/local/include/myheader.h" is a possible expansion of this macro.
__LINE__
This macro expands to the current input line number, in the form of a decimal integer constant. While we call it a predefined macro, it's a pretty strange macro,
since its "definition" changes with each new line of source code.
__FILE__ and __LINE__ are useful in generating an error message to report an inconsistency detected by the program; the message can state the source line
at which the inconsistency was detected. For example,
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 86 of 173
An #include directive changes the expansions of __FILE__ and __LINE__ to correspond to the included file. At the end of that file, when processing resumes on
the input file that contained the #include directive, the expansions of __FILE__ and __LINE__ revert to the values they had before the #include (but
__LINE__ is then incremented by one as processing moves to the line after the #include).
A #line directive changes __LINE__, and may change __FILE__ as well. See Line Control.
C99 introduces __func__, and GCC has provided __FUNCTION__ for a long time. Both of these are strings containing the name of the current function (there are
slight semantic differences; see Function Names as Strings). Neither of them is a macro; the preprocessor does not know the name of the current function.
They tend to be useful in conjunction with __FILE__ and __LINE__, though.
__DATE__
This macro expands to a string constant that describes the date on which the preprocessor is being run. The string constant contains eleven characters and
looks like "Feb 12 1996". If the day of the month is less than 10, it is padded with a space on the left.
If GCC cannot determine the current date, it will emit a warning message (once per compilation) and __DATE__ will expand to "??? ?? ????".
__TIME__
This macro expands to a string constant that describes the time at which the preprocessor is being run. The string constant contains eight characters and looks
like "23:59:01".
If GCC cannot determine the current time, it will emit a warning message (once per compilation) and __TIME__ will expand to "??:??:??".
__STDC__
In normal operation, this macro expands to the constant 1, to signify that this compiler conforms to ISO Standard C. If GNU CPP is used with a compiler other
than GCC, this is not necessarily true; however, the preprocessor always conforms to the standard unless the '-traditional-cpp' option is used.
__STDC_VERSION__
This macro expands to the C Standard's version number, a long integer constant of the form yyyymmL where yyyy and mm are the year and month of the
Standard version. This signifies which version of the C Standard the compiler conforms to.
The value 199409L signifies the 1989 C standard as amended in 1994, which is the current default; the value 199901L signifies the 1999 revision of the C
standard. Support for the 1999 revision is not yet complete.
__STDC_HOSTED__
This macro is defined, with value 1, if the compiler's target is a hosted environment. A hosted environment has the complete facilities of the standard C library
available.
The common predefined macros are GNU C extensions. They are available with the same meanings regardless of the machine or operating system on which you
are using GNU C. Their names all start with double underscores.
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
__VERSION__
__STRICT_ANSI__
__BASE_FILE__
__INCLUDE_LEVEL__
__OPTIMIZE__
__OPTIMIZE_SIZE__
__NO_INLINE__
__CHAR_UNSIGNED__
__CHAR_BIT__
__INT_SHORT__
__SCHAR_MAX__, __SHRT_MAX__, __INT_MAX__, __LONG_MAX__, __LONG_LONG_MAX__
__REGISTER_PREFIX__
__USER_LABEL_PREFIX__
__GNUC__
This macro is always defined in GCC. The value identifies the GCC major version number (currently '3').
If all you need to know is whether or not your program is being compiled by GCC, you can simply test __GNUC__. If you need to write code which depends on a
specific version, you must be more careful. Each time the minor version is increased, the patch level is reset to zero; each time the major version is increased
(which happens rarely), the minor version and patch level are reset. If you wish to use the predefined macros directly in the conditional, you will need to write
it like this:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 87 of 173
Another approach is to use the predefined macros to calculate a single number, then compare that against a threshold:
__GNUC_MINOR__
The macro contains the minor version number of the compiler. This can be used to work around differences between different releases of the compiler. It must
always be used together with __GNUC__.
__GNUC_PATCHLEVEL__
The macro contains the bugfix version number of the compiler. This can be used to work around differences between different releases of the compiler. It must
always be used together with __GNUC__ and __GNUC_MINOR__.
__GNUC_PATCHLEVEL__ is new to GCC 3.0; it is also present in the widely-used development snapshots leading up to 3.0 (which identify themselves as GCC
2.96 or 2.97, depending on which snapshot you have).
__VERSION__
This macro expands to a string constant which describes the version of the compiler in use. You should not rely on its contents having any particular form, but it
can be counted on to contain at least the release number.
__STRICT_ANSI__
GCC defines this macro if and only if the '-ansi' switch, or a '-std' switch specifying strict conformance to some version of ISO C, was specified when GCC was
invoked. It is defined to 1. This macro exists primarily to direct GNU libc's header files to restrict their definitions to the minimal set found in the 1989 C
standard.
__BASE_FILE__
This macro expands to the name of the main input file, in the form of a C string constant. This is the source file that was specified on the command line of the
preprocessor or C compiler.
__INCLUDE_LEVEL__
This macro expands to a decimal integer constant that represents the depth of nesting in include files. The value of this macro is incremented on every
#include directive and decremented at the end of every included file. It starts out at 0, its value within the base file specified on the command line.
__OPTIMIZE__
GNU CC defines this macro in optimizing compilations. Along with __OPTIMIZE_SIZE__ and __NO_INLINE__, it allows certain header files to define alternative
macro definitions for some system library functions. You should not refer to or test the definition of this macro unless you make very sure that programs will
execute with the same effect regardless. If it is defined, its value is 1.
__OPTIMIZE_SIZE__
This macro is defined in addition to __OPTIMIZE__ if the compiler is optimizing for size, not speed.
__NO_INLINE__
This macro is defined if no functions will be inlined into their callers (when not optimizing, or when inlining has been specifically disabled by '-fno-inline').
__CHAR_UNSIGNED__
This macro is defined if and only if the data type char is unsigned. Note that this is not true on TIGCC by default, but it may be changed using some compiler
command switches. It exists to cause the standard header file limits.h to work correctly. You should not refer to this macro yourself; instead, refer to the
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 88 of 173
__CHAR_BIT__
Defined to the number of bits used in the representation of the char data type. It exists to make the standard header given numerical limits work correctly. You
should not use this macro directly; instead, include the appropriate headers.
__INT_SHORT__
TIGCC defines this macro if and only if the data type int represents a short integer (short). Note that this is always true in TIGCC by default, but it may be
changed using some compiler command line switches. It exists to cause the standard header file limits.h to work correctly. You should not refer to this macro
yourself; instead, refer to the standard macros defined in limits.h.
Defined to the maximum value of the signed char, signed short, signed int, signed long, and signed long long types, respectively. They exist to make
the standard header given numerical limits work correctly. You should not use these macros directly; instead, include the appropriate headers.
__REGISTER_PREFIX__
This macro expands to a single token (not a string constant) which is the prefix applied to CPU register names in assembly language for this target. You can use
it to write assembly that is usable in multiple environments. For example, in the m68k-aout environment it expands to nothing, but in the m68k-coff
environment (as TIGCC is) it expands to a single %.
__USER_LABEL_PREFIX__
This macro expands to a single token which is the prefix applied to user labels (symbols visible to C code) in assembly. For example, in the m68k-aout
environment it expands to an _, but in the m68k-coff environment (as TIGCC is) it expands to nothing.
This macro will have the correct definition even if '-f(no-)underscores' is in use, but it will not be correct if target-specific options that adjust this prefix are
used (e.g. the OSF/rose '-mno-underscores' option).
The C preprocessor normally predefines several macros that indicate what type of system and machine is in use. They are obviously different on each target
supported by GCC. TIGCC currently defines only two such macros: mc68000 (predefined on most computers whose CPU is a Motorola 68000, 68010 or 68020)
and __embedded__. You can use cpp -dM to see all macros defined (see Invocation). All system-specific predefined macros expand to the constant 1, so you
can test them with either #ifdef or #if.
The C standard requires that all system-specific macros be part of the reserved namespace. All names which begin with two underscores, or an underscore and
a capital letter, are reserved for the compiler and library to use as they wish. However, historically system-specific macros have had names with no special
prefix; for instance, it is common to find unix defined on Unix systems. For all such macros, GCC provides a parallel macro with two underscores added at the
beginning and the end. If unix is defined, __unix__ will be defined too. There will never be more than two underscores; the parallel of _mips is __mips__.
When the '-ansi' option, or any '-std' option that requests strict conformance, is given to the compiler, all the system-specific predefined macros outside the
reserved namespace are suppressed. The parallel macros, inside the reserved namespace, remain defined.
We are slowly phasing out all predefined macros which are outside the reserved namespace. You should never use them in new programs, and we encourage
you to correct older code to use the parallel macros whenever you find it. We don't recommend you use the system-specific macros that are in the reserved
namespace, either. It is better in the long run to check specifically for features you need, using a tool such as autoconf.
Occasionally it is convenient to use preprocessor directives within the arguments of a macro. The C and C++ standards declare that behavior in these cases is
undefined.
Versions of CPP prior to 3.2 would reject such constructs with an error message. This was the only syntactic difference between normal functions and function-
like macros, so it seemed attractive to remove this limitation, and people would often be surprised that they could not use macros in this way. Moreover,
sometimes people would use conditional compilation in the argument list to a normal library function like printf, only to find that after a library upgrade
printf had changed to be a function-like macro, and their code would no longer compile. So from version 3.2 we changed CPP to successfully process arbitrary
directives within macro arguments in exactly the same way as it would have processed the directive were the function-like macro invocation not present.
If, within a macro invocation, that macro is redefined, then the new definition takes effect in time for argument pre-expansion, but the original definition is still
used for argument replacement. Here is a pathological example:
#define f(x) x x
f (1
#undef f
#define f 2
f)
which expands to
1 2 1 2
Macro Pitfalls
Previous Macros
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 89 of 173
In this section, we describe some special rules that apply to macros and macro expansion, and point out certain cases in which the rules have counter-intuitive
consequences that you must watch out for.
Misnesting
Operator Precedence Problems
Swallowing the Semicolon
Duplication of Side Effects
Self-Referential Macros
Argument Prescan
Newlines in Arguments
Misnesting
When a macro is called with arguments, the arguments are substituted into the macro body and the result is checked, together with the rest of the input file,
for more macro calls. It is possible to piece together a macro call coming partially from the macro body and partially from the arguments. For example,
Macro definitions do not have to have balanced parentheses. By writing an unbalanced open parenthesis in a macro body, it is possible to create a macro call
that begins inside the macro body but ends outside of it. For example,
The ability to piece together a macro call can be useful, but the use of unbalanced open parentheses in a macro body is just confusing, and should be avoided.
You may have noticed that in most of the macro definition examples shown above, each occurrence of a macro argument name had parentheses around it. In
addition, another pair of parentheses usually surround the entire macro definition. Here is why it is best to write macros that way.
#define ceil_div(x, y) (x + y - 1) / y
whose purpose is to divide, rounding up. (One use for this operation is to compute how many int objects are needed to hold a certain number of char objects.)
Then suppose it is used as follows:
This does not do what is intended. The operator-precedence rules of C make it equivalent to this:
Unintended grouping can result in another way. Consider sizeof ceil_div(1, 2). That has the appearance of a C expression that would compute the size of
the type of ceil_div (1, 2), but in fact it means something very different. Here is what it expands to:
This would take the size of an integer and divide it by two. The precedence rules have put the division outside the sizeof when it was intended to be inside.
Parentheses around the entire macro definition prevent such problems. Here, then, is the recommended way to define ceil_div:
Often it is desirable to define a macro that expands into a compound statement. Consider, for example, the following macro, that advances a pointer (the
argument p says where to find it) across whitespace characters:
Here backslash-newline is used to split the macro definition, which must be a single logical line, so that it resembles the way such code would be laid out if not
part of a macro definition.
A call to this macro might be SKIP_SPACES (p, lim). Strictly speaking, the call expands to a compound statement, which is a complete statement with no
need for a semicolon to end it. However, since it looks like a function call, it minimizes confusion if you can use it like a function call, writing a semicolon
afterward, as in SKIP_SPACES (p, lim);
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 90 of 173
This can cause trouble before else statements, because the semicolon is actually a null statement. Suppose you write
if (*p != 0)
SKIP_SPACES (p, lim);
else ...
The presence of two statements - the compound statement and a null statement - in between the if condition and the else makes invalid C code.
The definition of the macro SKIP_SPACES can be altered to solve this problem, using a do ... while statement. Here is how:
which is one statement. The loop executes exactly once; most compilers generate no extra code for it.
When you use this macro with an argument containing a side effect, as shown here,
it expands as follows:
The function foo is used only once in the statement as it appears in the program, but the expression foo (z) has been substituted twice into the macro
expansion. As a result, foo might be called two times when the statement is executed. If it has side effects or if it takes a long time to compute, the results
might not be what you intended. We say that min is an unsafe macro.
The best solution to this problem is to define min in a way that computes the value of foo (z) only once. The C language offers no standard way to do this, but
it can be done with GNU extensions as follows:
#define min(X, Y) \
({ typeof (X) x_ = (X); \
typeof (Y) y_ = (Y); \
(x_ < y_) ? x_ : y_; })
The ({ ... }) notation produces a compound statement that acts as an expression. Its value is the value of its last statement. This permits us to define local
variables and assign each argument to one. The local variables have underscores after their names to reduce the risk of conflict with an identifier of wider scope
(it is impossible to avoid this entirely). Now each argument is evaluated exactly once.
If you do not wish to use GNU C extensions, the only solution is to be careful when using the macro min. For example, you can calculate the value of foo (z),
save it in a variable, and use that variable in min:
Self-Referential Macros
A self-referential macro is one whose name appears in its definition. Recall that all macro definitions are rescanned for more macros to replace. If the self-
reference were considered a use of the macro, it would produce an infinitely large expansion. To prevent this, the self-reference is not considered a macro call.
It is passed into the preprocessor output unchanged. Let's consider an example:
Following the ordinary rules, each reference to foo will expand into (4 + foo); then this will be rescanned and will expand into (4 + (4 + foo)); and so on
until the computer runs out of memory.
The self-reference rule cuts this process short after one step, at (4 + foo). Therefore, this macro definition has the possibly useful effect of causing the
program to add 4 to the value of foo wherever foo is referred to.
In most cases, it is a bad idea to take advantage of this feature. A person reading the program who sees that foo is a variable will not expect that it is a macro
as well. The reader will come across the identifier foo in the program and think its value should be that of the variable foo, whereas in fact the value is four
greater.
One common, useful use of self-reference is to create a macro which expands to itself. If you write
then the macro EPERM expands to EPERM. Effectively, it is left alone by the preprocessor whenever it's used in running text. You can tell that it's a macro with
#ifdef. You might do this if you want to define numeric constants with an enum, but have #ifdef be true for each constant.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 91 of 173
If a macro x expands to use a macro y, and the expansion of y refers to the macro x, that is an indirect self-reference of x. x is not expanded in this case
either. Thus, if we have
#define x (4 + y)
#define y (2 * x)
x expands to (4 + y)
expands to (4 + (2 * x))
y expands to (2 * x)
expands to (2 * (4 + y))
Each macro is expanded when it appears in the definition of the other macro, but not when it indirectly appears in its own definition.
Argument Prescan
Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringified or pasted with other tokens. After
substitution, the entire macro body, including the substituted arguments, is scanned again for macros to be expanded. The result is that the arguments are
scanned twice to expand macro calls in them.
Most of the time, this has no effect. If the argument contained any macro calls, they are expanded during the first scan. The result therefore contains no macro
calls, so the second scan does not change it. If the argument were substituted as given, with no prescan, the single remaining scan would find the same macro
calls and produce the same results.
You might expect the double scan to change the results when a self-referential macro is used in an argument of another macro (see Self-Referential Macros):
the self-referential macro would be expanded once in the first scan, and a second time in the second scan. However, this is not what happens. The self-
references that do not expand in the first scan are marked so that they will not expand in the second scan either.
You might wonder, "Why mention the prescan, if it makes no difference? And why not skip it and make the preprocessor faster?" The answer is that the prescan
does make a difference in three special cases:
We say that nested calls to a macro occur when a macro's argument contains a call to that very macro. For example, if f is a macro that expects one
argument, f (f (1)) is a nested pair of calls to f. The desired expansion is made by expanding f (1) and substituting that into the definition of f. The
prescan causes the expected result to happen. Without the prescan, f (1) itself would be substituted as an argument, and the inner use of f would
appear during the main scan as an indirect self-reference and would not be expanded.
If an argument is stringified or concatenated, the prescan does not occur. If you want to expand a macro, then stringify or concatenate its expansion, you
can do that by causing one macro to call another macro that does the stringification or concatenation. For instance, if you have
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE
then AFTERX(BUFSIZE) expands to X_BUFSIZE, and XAFTERX(BUFSIZE) expands to X_1024. (Not to X_TABLESIZE. Prescan always does a complete
expansion.)
This can cause a macro expanded on the second scan to be called with the wrong number of arguments. Here is an example:
We would like bar(foo) to turn into (1 + (foo)), which would then turn into (1 + (a,b)). Instead, bar(foo) expands into lose(a,b), and you get an
error because lose requires a single argument. In this case, the problem is easily solved by the same parentheses that ought to be used to prevent
misnesting of arithmetic operations:
The extra pair of parentheses prevents the comma in foo's definition from being interpreted as an argument separator.
Newlines in Arguments
The invocation of a function-like macro can extend over many logical lines. However, in the present implementation, the entire expansion comes out on one
line. Thus line numbers emitted by the compiler or debugger refer to the line the invocation started on, which might be different to the line containing the
argument causing the problem.
#define ignore_second_arg(a,b,c) a; c
The syntax error triggered by the tokens syntax error results in an error message citing line three - the line of ignore_second_arg - even though the
problematic code comes from line five.
Conditionals
A conditional is a directive that instructs the preprocessor to select whether or not to include a chunk of code in the final token stream passed to the compiler.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 92 of 173
Preprocessor conditionals can test arithmetic expressions, or whether a name is defined as a macro, or both simultaneously using the special defined operator.
A conditional in the C preprocessor resembles in some ways an if statement in C, but it is important to understand the difference between them. The condition
in an if statement is tested during the execution of your program. Its purpose is to allow your program to behave differently from run to run, depending on the
data it is operating on. The condition in a preprocessing conditional directive is tested when your program is compiled. Its purpose is to allow different code to
be included in the program depending on the situation at the time of compilation.
However, the distinction is becoming less clear. Modern compilers often do test if statements when a program is compiled, if their conditions are known not to
vary at run time, and eliminate code which can never be executed. If you can count on your compiler to do this, you may find that your program is more
readable if you use if statements with constant conditions (perhaps determined by macros). Of course, you can only use this to exclude code, not type
definitions or other preprocessing directives, and you can only do it if the code remains syntactically valid when it is not to be used.
GCC version 3 eliminates this kind of never-executed code even when not optimizing. Older versions did it only when optimizing.
Conditional Uses
Conditional Syntax
Deleted Code
Conditional Uses
Conditionals Next
A program may need to use different code depending on the machine or operating system it is to run on. In some cases the code for one operating
system may be erroneous on another operating system; for example, it might refer to data types or constants that do not exist on the other system.
When this happens, it is not enough to avoid executing the invalid code. Its mere presence will cause the compiler to reject the program. With a
preprocessing conditional, the offending code can be effectively excised from the program when it is not valid.
You may want to be able to compile the same source file into two different programs. One version might make frequent time-consuming consistency
checks on its intermediate data, or print the values of those data for debugging, and the other not.
A conditional whose condition is always false is one way to exclude code from the program but keep it as a sort of comment for future reference.
Simple programs that do not need system-specific logic or complex debugging hooks generally will not need to use preprocessing conditionals. In TIGCC,
conditionals are useful to select appropriate constants depending on which calculator and operating system the program is intended to run on, and to enable or
disable certain features.
Conditional Syntax
A conditional in the C preprocessor begins with a conditional directive: #if, #ifdef, or #ifndef.
#ifdef
#if
#else
#elif
#ifdef
#ifdef MACRO
controlled text
#endif /* MACRO */
This block is called a conditional group. controlled text will be included in the output of the preprocessor if and only if MACRO is defined. We say that the
conditional succeeds if MACRO is defined, fails if it is not.
The controlled text inside of a conditional can include preprocessing directives. They are executed only if the conditional succeeds. You can nest conditional
groups inside other conditional groups, but they must be completely nested. In other words, #endif always matches the nearest #ifdef (or #ifndef, or #if).
Also, you cannot start a conditional group in one file and end it in another.
Even if a conditional fails, the controlled text inside it is still run through initial transformations and tokenization. Therefore, it must all be lexically valid C.
Normally the only way this matters is that all comments and string literals inside a failing conditional group must still be properly ended.
The comment following the #endif is not required, but it is a good practice if there is a lot of controlled text, because it helps people match the #endif to the
corresponding #ifdef. Older programs sometimes put MACRO directly after the #endif without enclosing it in a comment. This is invalid code according to the
C standard. CPP accepts it with a warning. It never affects which #ifndef the #endif matches.
Sometimes you wish to use some code if a macro is not defined. You can do this by writing #ifndef instead of #ifdef. One common use of #ifndef is to
include code only the first time a header file is included. See Once-Only Headers.
Macro definitions can vary between compilations for several reasons. Here are some samples.
Some macros are predefined on each kind of machine (see System-specific Predefined Macros). This allows you to provide code specially tuned for a
particular machine.
System header files define more macros, associated with the features they implement. You can test these macros with conditionals to avoid using a
system feature on a machine where it is not implemented.
Macros can be defined or undefined with the '-D' and '-U' command line options when you compile the program. You can arrange to compile the same
source file into two different programs by choosing a macro name to specify which program you want, writing conditionals to test whether or how this
macro is defined, and then controlling the state of the macro with command line options, perhaps set in the Makefile. See Invocation.
Your program might have a special header file (often called config.h) that is adjusted when the program is compiled. It can define or not define macros
depending on the features of the system and the desired capabilities of the program. The adjustment can be automated by a tool such as autoconf, or
done by hand.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 93 of 173
#if
The #if directive allows you to test the value of an arithmetic expression, rather than the mere existence of one macro. Its syntax is
#if expression
controlled text
#endif /* expression */
Integer constants.
Arithmetic operators for addition, subtraction, multiplication, division, bitwise operations, shifts, comparisons, and logical operations (&& and ||). The
latter two obey the usual short-circuiting rules of standard C.
Macros. All macros in the expression are expanded before actual computation of the expression's value begins.
Uses of the defined operator, which lets you check whether macros are defined in the middle of an #if.
Identifiers that are not macros, which are all considered to be the number zero. This allows you to write #if MACRO instead of #ifdef MACRO, if you know
that MACRO, when defined, will always have a nonzero value. Function-like macros used without their function call parentheses are also treated as zero.
In some contexts this shortcut is undesirable. The '-Wundef' option causes GCC to warn whenever it encounters an identifier which is not a macro in an
#if.
The preprocessor does not know anything about types in the language. Therefore, sizeof operators are not recognized in #if, and neither are enum constants.
They will be taken as identifiers which are not macros, and replaced by zero. In the case of sizeof, this is likely to cause the expression to be invalid.
The preprocessor calculates the value of expression. It carries out all calculations in the widest integer type known to the compiler; on most machines
supported by GCC this is 64 bits. This is not the same rule as the compiler uses to calculate the value of a constant expression, and may give different results in
some cases. If the value comes out to be nonzero, the #if succeeds and the controlled text is included; otherwise it is skipped.
If expression is not correctly formed, GCC issues an error and treats the conditional as having failed.
defined
defined
#if
The special operator defined is used in #if and #elif expressions to test whether a certain name is defined as a macro. defined name and defined (name)
are both expressions whose value is 1 if name is defined as a macro at the current point in the program, and 0 otherwise. Thus, #if defined MACRO is
precisely equivalent to #ifdef MACRO.
defined is useful when you wish to test more than one macro for existence at once. For example,
can generally be simplified to just #if BUFSIZE >= 1024, since if BUFSIZE is not defined, it will be interpreted as having the value zero.
If the defined operator appears as a result of a macro expansion, the C standard says the behavior is undefined. GNU cpp treats it as a genuine defined
operator and evaluates it normally. It will warn wherever your code uses this feature if you use the command-line option '-pedantic', since other compilers
may handle it differently.
#else
The #else directive can be added to a conditional to provide alternative text to be used if the condition fails. This is what it looks like:
#if expression
text-if-true
#else /* Not expression */
text-if-false
#endif /* Not expression */
If expression is nonzero, the text-if-true is included and the text-if-false is skipped. If expression is zero, the opposite happens.
#elif
One common case of nested conditionals is used to check for more than two possible alternatives. For example, you might have
#if X == 1
...
#else /* X != 1 */
#if X == 2
...
#else /* X != 2 */
...
#endif /* X != 2 */
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 94 of 173
#endif /* X != 1 */
#if X == 1
...
#elif X == 2
...
#else /* X != 2 and X != 1 */
...
#endif /* X != 2 and X != 1 */
#elif stands for "else if". Like #else, it goes in the middle of a conditional group and subdivides it; it does not require a matching #endif of its own. Like #if,
the #elif directive includes an expression to be tested. The text following the #elif is processed only if the original #if-condition failed and the #elif
condition succeeds.
More than one #elif can go in the same conditional group. Then the text after each #elif is processed only if the #elif condition succeeds after the original
#if and all previous #elif directives within it have failed.
#else is allowed after any number of #elif directives, but #elif may not follow #else.
Deleted Code
Previous Conditionals
If you replace or delete a part of the program but want to keep the old code around for future reference, you often cannot simply comment it out. Block
comments do not nest, so the first comment inside the old code will end the commenting-out. The probable result is a flood of syntax errors.
One way to avoid this problem is to use an always-false conditional instead. For instance, put #if 0 before the deleted code and #endif after it. This works
even if the code being turned off contains conditionals, but they must be entire conditionals (balanced #if and #endif).
Some people use #ifdef notdef instead. This is risky, because notdef might be accidentally defined as a macro, and then the conditional would succeed.
#if 0 can be counted on to fail.
Do not use #if 0 for comments which are not C code. Use a real comment, instead. The interior of #if 0 must consist of complete tokens; in particular, single-
quote characters must balance. Comments often contain unbalanced single-quote characters (known in English as apostrophes). These confuse #if 0. They
don't confuse /*.
Pragmas
The #pragma directive is the method specified by the C standard for providing additional information to the compiler, beyond what is conveyed in the language
itself. Three forms of this directive (commonly known as pragmas) are specified by the 1999 C standard. A C compiler is free to attach any meaning it likes to
other pragmas.
GCC has historically preferred to use extensions to the syntax of the language, such as __attribute__, for this purpose. However, GCC does define a few
pragmas of its own. These mostly have effects on the entire translation unit or source file.
In GCC version 3, all GNU-defined, supported pragmas have been given a GCC prefix. This is in line with the STDC prefix on all pragmas defined by C99. For
backward compatibility, pragmas which were recognized by previous versions are still recognized without the GCC prefix, but that usage is deprecated. Some
older pragmas are deprecated in their entirety. They are not recognized with the GCC prefix. See Obsolete Features.
C99 introduces the _Pragma operator. This feature addresses a major problem with #pragma: being a directive, it cannot be produced as the result of macro
expansion. _Pragma is an operator, much like sizeof or defined, and can be embedded in a macro.
Its syntax is _Pragma (string-literal), where string-literal can be either a normal or wide-character string literal. It is destringized, by replacing all \\ with a
single \ and all \" with a ". The result is then processed as if it had appeared as the right hand side of a #pragma directive. For example,
has the same effect as #pragma GCC dependency "parse.y". The same effect could be achieved using macros, for example
The standard is unclear on where a _Pragma operator can appear. The preprocessor does not accept it within a preprocessing conditional directive like #if. To
be safe, you are probably best keeping it out of directives other than #define, and putting it on a line of its own.
This manual documents the pragmas which are meaningful to the preprocessor itself. Other pragmas are meaningful to the compiler. They are documented in
the GCC manual.
If a poisoned identifier appears as part of the expansion of a macro which was defined before the identifier was poisoned, it will not cause an error. This
lets you poison an identifier without worrying about system headers defining macros that use it.
For example,
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 95 of 173
Other Directives
The #ident directive takes one argument, a string constant. On some systems, that string constant is copied into a special segment of the object file. On other
systems, the directive is ignored.
This directive is not part of the C standard, but it is not an official GNU extension either. We believe it came from System V.
The #sccs directive is recognized, because it appears in the header files of some systems. It is a very old, obscure, extension which we did not invent, and we
have been unable to find any documentation of what it should do, so GCC simply ignores it.
The null directive consists of a # followed by a newline, with only whitespace (including comments) in between. A null directive is understood as a preprocessing
directive but has no effect on the preprocessor output. The primary significance of the existence of the null directive is that an input line consisting of just a #
will produce no output, rather than a line of output containing just a #. Supposedly some old C programs contain such lines.
User-defined Diagnostics
The directive #error causes the preprocessor to report a fatal error. The tokens forming the rest of the line following #error are used as the error message.
You would use #error inside of a conditional that detects a combination of parameters which you know the program does not properly support. For example, if
you know that the program will not run properly on a VAX, you might write
#ifdef __vax__
#error "Won't work on VAXen. See comments at get_last_object."
#endif
If you have several configuration parameters that must be set up by the installation in a consistent way, you can use conditionals to detect an inconsistency
and report it with #error. For example,
The directive #warning is like #error, but causes the preprocessor to issue a warning and continue preprocessing. The tokens following #warning are used as
the warning message.
You might use #warning in obsolete header files, with a message directing the user to the header file which should be used instead.
Neither #error nor #warning macro-expands its argument. Internal whitespace sequences are each replaced with a single space. The line must consist of
complete tokens. It is wisest to make the argument of these directives be a single string constant; this avoids problems with apostrophes and the like.
Line Control
The C preprocessor informs the C compiler of the location in your source code where each token came from. Presently, this is just the file name and line
number. All the tokens resulting from macro expansion are reported as having appeared on the line of the source file where the outermost macro was used. We
intend to be more accurate in the future.
If you write a program which generates source code, such as the bison parser generator, you may want to adjust the preprocessor's notion of the current file
name and line number by hand. Parts of the output from bison are generated from scratch, other parts come from a standard parser file. The rest are copied
verbatim from bison's input. You would like compiler error messages and symbolic debuggers to be able to refer to bison's input file.
bison or any such program can arrange this by writing #line directives into the output file. #line is a directive that specifies the original line number and
source file name for subsequent input in the current preprocessor input file. #line has three variants:
#line linenum
linenum is a non-negative decimal integer constant. It specifies the line number which should be reported for the following line of input. Subsequent lines
are counted from linenum.
Previous versions of CPP did not interpret escapes in #line; we have changed it because the standard requires they be interpreted, and most other
compilers do.
#line directives alter the results of the __FILE__ and __LINE__ predefined macros from that point on. See Standard Predefined Macros. They do not have any
effect on #include's idea of the directory containing the current file. This is a change from GCC 2.95. Previously, a file reading
#line 1 "../src/gram.y"
#include "gram.h"
would search for gram.h in ../src, then the '-I' chain; the directory containing the physical source file would not be searched. In GCC 3.0 and later, the
#include is not affected by the presence of a #line referring to a different directory.
We made this change because the old behavior caused problems when generated source files were transported between machines. For instance, it is common
practice to ship generated parsers with a source release, so that people building the distribution do not need to have yacc or Bison installed. These files
frequently have #line directives referring to the directory tree of the system where the distribution was created. If GCC tries to search for headers in those
directories, the build is likely to fail.
The new behavior can cause failures too, if the generated file is not in the same directory as its source and it attempts to include a header which would be
visible searching from the directory containing the source file. However, this problem is easily solved with an additional '-I' switch on the command line. The
failures caused by the old semantics could sometimes be corrected only by editing the generated files, which is difficult and error-prone.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 96 of 173
Preprocessor Output
When the C preprocessor is used with the C, C++, or Objective-C compilers, it is integrated into the compiler and communicates a stream of binary tokens
directly to the compiler's parser. However, it can also be used in the more conventional standalone mode, where it produces textual output.
The output from the C preprocessor looks much like the input, except that all preprocessing directive lines have been replaced with blank lines and all
comments with spaces. Long runs of blank lines are discarded.
The ISO standard specifies that it is implementation defined whether a preprocessor preserves whitespace between tokens, or replaces it with e.g. a single
space. In GNU CPP, whitespace between tokens is collapsed to become a single space, with the exception that the first token on a non-directive line is preceded
with sufficient spaces that it appears in the same column in the preprocessed output that it appeared in the original source file. This is so the output is easy to
read. See Differences from previous versions. CPP does not insert any whitespace where there was none in the original source, except where necessary to
prevent an accidental token paste.
Source file name and line number information is conveyed by lines of the form
These are called linemarkers. They are inserted as needed into the output (but never within a string or character constant). They mean that the following line
originated in file filename at line linenum. filename will never contain any non-printing characters; they are replaced with octal escape sequences.
After the file name comes zero or more flags, which are 1, 2, 3, or 4. If there are multiple flags, spaces separate them. Here is what the flags mean:
1
This indicates the start of a new file.
2
This indicates returning to a file (after having included another file).
3
This indicates that the following text comes from a system header file, so certain warnings should be suppressed.
4
This indicates that the following text should be treated as being wrapped in an implicit extern "C" block.
As an extension, the preprocessor accepts linemarkers in non-assembler input files. They are treated like the corresponding #line directive, (see Line Control),
except that trailing flags are permitted, and are interpreted with the meanings described above. If multiple flags are given, they must be in ascending order.
Some directives may be duplicated in the output of the preprocessor. These are #ident (always), #pragma (only if the preprocessor does not handle the pragma
itself), and #define and #undef (with certain debugging options). If this happens, the # of the directive will always be in the first column, and there will be no
space between the # and the directive name. If macro expansion happens to generate tokens which might be mistaken for a duplicated directive, a space will
be inserted between the # and the directive name.
Most often, when you use the C preprocessor, you will not have to invoke it explicitly: the C compiler will do so automatically. However, the preprocessor is
sometimes useful on its own. All the options listed here are also acceptable to the C compiler and have the same meaning, except that the C compiler has
different rules for specifying the output file.
Note: Whether you use the preprocessor by way of gcc or cpp, the compiler driver is run first. This program's purpose is to translate your command into
invocations of the programs that do the actual work. Their command line interfaces are similar but not identical to the documented interface, and may change
without notice.
The C preprocessor expects two file names as arguments, infile and outfile. The preprocessor reads infile together with any other files it specifies with
#include. All the output generated by the combined input files is written in outfile.
Either infile or outfile may be '-', which as infile means to read from standard input and as outfile means to write to standard output. Also, if either file is
omitted, it means the same as if '-' had been specified for that file.
Unless otherwise noted, or the option ends in =, all options which take an argument may have that argument appear either immediately after the option, or
with a space between option and argument: '-Ifoo' and '-I foo' have the same effect.
Many options have multi-letter names; therefore multiple single-letter options may not be grouped: '-dM' is very different from '-d -M'.
For the actual command-line options, see GCC Options Controlling the Preprocessor.
This section describes the environment variables that affect how CPP operates. You can use them to specify directories or prefixes to use when searching for
include files, or to control dependency output.
Note that you can also specify places to search using options such as '-I', and control dependency output with options like '-M' (see Invocation). These take
precedence over environment variables, which in turn take precedence over the configuration of GCC.
CPATH
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
OBJC_INCLUDE_PATH
Each variable's value is a list of directories separated by a special character, much like PATH, in which to look for header files. The special character,
PATH_SEPARATOR, is target-dependent and determined at GCC build time. For Windows-based targets it is a semicolon, and for almost all other targets it
is a colon.
CPATH specifies a list of directories to be searched as if specified with '-I', but after any paths given with '-I' options on the command line. This
environment variable is used regardless of which language is being preprocessed.
The remaining environment variables apply only when preprocessing the particular language indicated. Each specifies a list of directories to be searched
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 97 of 173
as if specified with '-isystem', but after any paths given with '-isystem' options on the command line.
In all these variables, an empty element instructs the compiler to search its current working directory. Empty elements can appear at the beginning or
end of a path. For instance, if the value of CPATH is :/special/include, that has the same effect as -I. -I/special/include.
DEPENDENCIES_OUTPUT
If this variable is set, its value specifies how to output dependencies for Make based on the non-system header files processed by the compiler. System
header files are ignored in the dependency output.
The value of DEPENDENCIES_OUTPUT can be just a file name, in which case the Make rules are written to that file, guessing the target name from the
source file name. Or the value can have the form file target, in which case the rules are written to file file using target as the target name.
In other words, this environment variable is equivalent to combining the options '-MM' and '-MF' (see Invocation), with an optional '-MT' switch too.
SUNPRO_DEPENDENCIES
This variable is the same as DEPENDENCIES_OUTPUT (see above), except that system header files are not ignored, so it implies '-M' rather than '-MM'.
However, the dependence on the main input file is omitted. See Invocation.
Traditional Mode
Traditional (pre-standard) C preprocessing is rather different from the preprocessing specified by the standard. When GCC is given the '-traditional-cpp'
option, it attempts to emulate a traditional preprocessor.
GCC versions 3.2 and later only support traditional mode semantics in the preprocessor, and not in the compiler front ends. This chapter outlines the traditional
preprocessor semantics implemented by GNU. Note, however, that you cannot use traditional mode preprocessing if you include header files from the TIGCC
Library; this section is included only for reference, for people who want their programs to be compilable with traditional compilers.
The implementation does not correspond precisely to the behavior of earlier versions of GCC, nor to any true traditional preprocessor. After all, inconsistencies
among traditional implementations were a major motivation for C standardization. However, we intend that it should be compatible with true traditional
preprocessors in all ways that actually matter.
The traditional preprocessor does not decompose its input into tokens the same way a standards-conforming preprocessor does. The input is simply treated as
a stream of text with minimal internal form.
This implementation does not treat trigraphs (see Initial Processing) specially since they were an invention of the standards committee. It handles arbitrarily-
positioned escaped newlines properly and splices the lines as you would expect; many traditional preprocessors did not do this.
The form of horizontal whitespace in the input file is preserved in the output. In particular, hard tabs remain hard tabs. This can be useful if, for example, you
are preprocessing a Makefile.
Traditional CPP only recognizes C-style block comments, and treats the /* sequence as introducing a comment only if it lies outside quoted text. Quoted text is
introduced by the usual single and double quotes, and also by an initial < in a #include directive.
Traditionally, comments are completely removed and are not replaced with a space. Since a traditional compiler does its own tokenization of the output of the
preprocessor, this means that comments can effectively be used as token paste operators. However, comments behave like separators for text handled by the
preprocessor itself, since it doesn't re-lex its input. For example, in
#if foo/**/bar
foo and bar are distinct identifiers and expanded separately if they happen to be macros. In other words, this directive is equivalent to
rather than
#if foobar
Generally speaking, in traditional mode an opening quote need not have a matching closing quote. In particular, a macro may be defined with replacement text
that contains an unmatched quote. Of course, if you attempt to compile preprocessed output containing an unmatched quote you will get a syntax error.
However, all preprocessing directives other than #define require matching quotes. For example:
Just as for the ISO preprocessor, what would be a closing quote can be escaped with a backslash to prevent the quoted text from closing.
Traditional macros
The major difference between traditional and ISO macros is that the former expand to text rather than to a token sequence. CPP removes all leading and
trailing horizontal whitespace from a macro's replacement text before storing it, but preserves the form of internal whitespace.
One consequence is that it is legitimate for the replacement text to contain an unmatched quote (see Traditional lexical analysis). An unclosed string or
character constant continues into the text following the macro call. Similarly, the text at the end of a macro's expansion can run together with the text after the
macro invocation to produce a single token.
Normally comments are removed from the replacement text after the macro is expanded, but if the '-CC' option is passed on the command line comments are
preserved. (In fact, the current implementation removes comments even before saving the macro replacement text, but it careful to do it in such a way that the
observed effect is identical even in the function-like macro case.)
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 98 of 173
The ISO stringification operator # and token paste operator ## have no special meaning. As explained later, an effect similar to these operators can be obtained
in a different way. Macro names that are embedded in quotes, either from the main file or after macro replacement, do not expand.
CPP replaces an unquoted object-like macro name with its replacement text, and then rescans it for further macros to replace. Unlike standard macro
expansion, traditional macro expansion has no provision to prevent recursion. If an object-like macro appears unquoted in its replacement text, it will be
replaced again during the rescan pass, and so on ad infinitum. GCC detects when it is expanding recursive macros, emits an error message, and continues after
the offending macro invocation.
#define PLUS +
#define INC(x) PLUS+x
INC(foo);
expands to ++foo;
Function-like macros are similar in form but quite different in behavior to their ISO counterparts. Their arguments are contained within parentheses, are
comma-separated, and can cross physical lines. Commas within nested parentheses are not treated as argument separators. Similarly, a quote in an argument
cannot be left unclosed; a following comma or parenthesis that comes before the closing quote is treated like any other character. There is no facility for
handling variadic macros.
This implementation removes all comments from macro arguments, unless the '-C' option is given. The form of all other horizontal whitespace in arguments is
preserved, including leading and trailing whitespace. In particular
f( )
is treated as an invocation of the macro f with a single argument consisting of a single space. If you want to invoke a function-like macro that takes no
arguments, you must not leave any whitespace between the parentheses.
If a macro argument crosses a new line, the new line is replaced with a space when forming the argument. If the previous line contained an unterminated
quote, the following line inherits the quoted state.
Traditional preprocessors replace parameters in the replacement text with their arguments regardless of whether the parameters are within quotes or not. This
provides a way to stringize arguments. For example
Note that the comment is removed, but that the trailing space is preserved. Here is an example of using a comment to effect token pasting.
Traditional miscellany
Here are some things to be aware of when using the traditional preprocessor.
Preprocessing directives are recognized only when their leading # appears in the first column. There can be no whitespace between the beginning of the
line and the #, but whitespace can follow the #.
A true traditional C preprocessor does not recognize #error or #pragma, and may not recognize #elif. CPP supports all the directives in traditional mode
that it supports in ISO mode, including extensions, with the exception that the effects of #pragma GCC poison are undefined.
If a line that looks like a directive appears within macro arguments, the behavior is undefined.
Traditional warnings
You can request warnings about features that did not exist, or worked differently, in traditional C with the '-Wtraditional' option. GCC does not warn about
features of ISO C which you must use when you are using a conforming compiler, such as the # and ## operators.
Macro parameters that appear within string literals in the macro body. In traditional C macro replacement takes place within string literals, but does not in
ISO C.
In traditional C, some preprocessor directives did not exist. Traditional preprocessors would only consider a line to be a directive if the # appeared in
column 1 on the line. Therefore '-Wtraditional' warns about directives that traditional C understands but would ignore because the # does not appear as
the first character on the line. It also suggests you hide directives like #pragma not understood by traditional C by indenting them. Some traditional
implementations would not recognize #elif, so it suggests avoiding it altogether.
A function-like macro that appears without an argument list. In some traditional preprocessors this was an error. In ISO C it merely means that the macro
is not expanded.
The U and LL integer constant suffixes, which were not available in traditional C. (Traditional C does support the L suffix for simple long integer
constants.) You are not warned about uses of these suffixes in macros defined in system headers. For instance, UINT_MAX may well be defined as
4294967295U, but you will not be warned if you use UINT_MAX.
You can usually avoid the warning, and the related warning about constants which are so large that they are unsigned, by writing the integer constant in
question in hexadecimal, with no U suffix. Take care, though, because this gives the wrong result in exotic cases.
Implementation Details
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 99 of 173
Here we document details of how the preprocessor's implementation affects its user-visible behavior. You should try to avoid undue reliance on behavior
described here, as it is possible that it will change subtly in future implementations.
Also documented here are obsolete features and changes from previous versions of CPP.
Implementation-defined Behavior
Implementation Limits
Obsolete Features
Differences from Previous Versions
Implementation-defined Behavior
This is how CPP behaves in all the cases which the C standard describes as implementation-defined. This term means that the implementation is free to do what
it likes, but must document its choice and stick to it.
The mapping of physical source file multi-byte characters to the execution character set.
Currently, GNU cpp only supports character sets that are strict supersets of ASCII, and performs no translation of characters.
Non-empty sequences of whitespace characters. In textual output, each whitespace sequence is collapsed to a single space. For aesthetic reasons, the
first token on each non-directive line of output is preceded with sufficient spaces that it appears in the same column as it did in the original source file.
The numeric value of character constants in preprocessor expressions. The preprocessor and compiler interpret character constants in the same way; i.e.
escape sequences such as \a are given the values they would have on the target machine.
The compiler values a multi-character character constant a character at a time, shifting the previous value left by the number of bits per target character,
and then or-ing in the bit-pattern of the new character truncated to the width of a target character. The final bit-pattern is given type int, and is
therefore signed, regardless of whether single characters are signed or not (a slight change from versions 3.1 and earlier of GCC). If there are more
characters in the constant than would fit in the target int the compiler issues a warning, and the excess leading characters are ignored.
For example, 'ab' for a target with an 8-bit char would be interpreted as (int) ((unsigned char) 'a' * 256 + (unsigned char) 'b'), and '\234a' as (int)
((unsigned char) '\234' * 256 + (unsigned char) 'a').
Source file inclusion. For a discussion on how the preprocessor locates header files, see Include Operation.
No macro expansion occurs on any #pragma directive line, so the question does not arise.
Note that GCC does not yet implement any of the standard pragmas.
Implementation Limits
CPP has a small number of internal limits. This section lists the limits which the C standard requires to be no lower than some minimum, and all the others we
are aware of. We intend there to be as few limits as possible. If you encounter an undocumented or inconvenient limit, please report that to us as a bug. (See
the section on reporting bugs in the GCC manual.)
Where we say something is limited only by available memory, that means that internal data structures impose no intrinsic limit, and space is allocated with
malloc or equivalent. The actual limit will therefore depend on many things, such as the size of other things allocated by the compiler at the same time, the
amount of memory consumed by other processes on the same computer, etc.
Nesting levels of #include files. We impose an arbitrary limit of 200 levels, to avoid runaway recursion. The standard requires at least 15 levels.
Nesting levels of conditional inclusion. The C standard mandates this be at least 63. CPP is limited only by available memory.
Levels of parenthesized expressions within a full expression. The C standard requires this to be at least 63. In preprocessor conditional expressions, it is
limited only by available memory.
Significant initial characters in an identifier or macro name. The preprocessor treats all characters as significant. The C standard requires only that the
first 63 be significant.
Number of macros simultaneously defined in a single translation unit. The standard requires at least 4095 be possible. CPP is limited only by available
memory.
Number of parameters in a macro definition and arguments in a macro call. We allow USHRT_MAX, which is no smaller than 65,535. The minimum required
by the standard is 127.
Number of characters on a logical source line. The C standard requires a minimum of 4096 be permitted. CPP places no limits on this, but you may get
incorrect column numbers reported in diagnostics for lines longer than 65,535 characters.
Maximum size of a source file. The standard does not specify any lower limit on the maximum size of a source file. GNU cpp maps files into memory, so it
is limited by the available address space. This is generally at least two gigabytes. Depending on the operating system, the size of physical memory may
or may not be a limitation.
Obsolete Features
CPP has a number of features which are present mainly for compatibility with older programs. We discourage their use in new code. In some cases, we plan to
remove the feature in a future version of GCC.
Assertions
Obsolete Once-Only Headers
Miscellaneous Obsolete Features
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 100 of 173
Assertions
Assertions are a deprecated alternative to macros in writing conditionals to test what sort of computer or system the compiled program will run on. Assertions
are usually predefined, but you can define them with preprocessing directives or command-line options.
Assertions were intended to provide a more systematic way to describe the compiler's target system. However, in practice they are just as unpredictable as the
system-specific predefined macros. In addition, they are not part of any standard, and only a few compilers support them. Therefore, the use of assertions is
less portable than the use of system-specific predefined macros. We recommend you do not use them at all.
#predicate (answer)
predicate must be a single identifier. answer can be any sequence of tokens; all characters are significant except for leading and trailing whitespace, and
differences in internal whitespace sequences are ignored. (This is similar to the rules governing macro redefinition.) Thus, (x + y) is different from (x+y) but
equivalent to ( x + y ). Parentheses do not nest inside an answer.
To test an assertion, you write it in an #if. For example, this conditional succeeds if either vax or ns16000 has been asserted as an answer for machine.
You can test whether any answer is asserted for a predicate by omitting the answer in the conditional:
#if #machine
Assertions are made with the #assert directive. Its sole argument is the assertion to make, without the leading # that identifies assertions in conditionals.
You may make several assertions with the same predicate and different answers. Subsequent assertions do not override previous ones for the same predicate.
All the answers for any given predicate are simultaneously true.
Assertions can be canceled with the #unassert directive. It has the same syntax as #assert. In that form it cancels only the answer which was specified on the
#unassert line; other answers for that predicate remain true. You can cancel an entire predicate by leaving out the answer:
#unassert predicate
In either form, if no such assertion has been made, #unassert has no effect.
You can also make or cancel assertions using command line options. See Invocation.
CPP supports two more ways of indicating that a header file should be read only once. Neither one is as portable as a wrapper #ifndef, and we recommend you
do not use them in new programs.
In the Objective-C language, there is a variant of #include called #import which includes a file, but does so at most once. If you use #import instead of
#include, then you don't need the conditionals inside the header file to prevent multiple inclusion of the contents. GCC permits the use of #import in C and
C++ as well as Objective-C. However, it is not in standard C or C++ and should therefore not be used by portable programs.
#import is not a well designed feature. It requires the users of a header file to know that it should only be included once. It is much better for the header file's
implementor to write the file so that users don't need to know this. Using a wrapper #ifndef accomplishes this goal.
In the present implementation, a single use of #import will prevent the file from ever being read again, by either #import or #include. You should not rely on
this; do not use both #import and #include to refer to the same header file.
Another way to prevent a header file from being included more than once is with the #pragma once directive. If #pragma once is seen when scanning a header
file, that file will never be read again, no matter what.
#pragma once does not have the problems that #import does, but it is not recognized by all preprocessors, so you cannot rely on it in a portable program.
#pragma poison This is the same as #pragma GCC poison. The version without the GCC prefix is deprecated. See Pragmas.
This section details behavior which has changed from previous versions of CPP. We do not plan to change it again in the near future, but we do not promise not
to, either.
The "previous versions" discussed here are 2.95 and before. The behavior of GCC 3.0 is mostly the same as the behavior of the widely used 2.96 and 2.97
development snapshots. Where there are differences, they generally represent bugs in the snapshots.
Order of evaluation of # and ## operators: The standard does not specify the order of evaluation of a chain of ## operators, nor whether # is evaluated
before, after, or at the same time as ##. You should therefore not write any code which depends on any specific ordering. It is possible to guarantee an
ordering, if you need one, by suitable use of nested macros.
An example of where this might matter is pasting the arguments 1, e and '-2'. This would be fine for left-to-right pasting, but right-to-left pasting would
produce an invalid token e-2.
GCC 3.0 evaluates # and ## at the same time and strictly left to right. Older versions evaluated all # operators first, then all ## operators, in an unreliable
order.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 101 of 173
The form of whitespace between tokens in preprocessor output: Preprocessor Output, for the current textual format. This is also the format used by
stringification. Normally, the preprocessor communicates tokens directly to the compiler's parser, and whitespace does not come up at all.
Older versions of GCC preserved all whitespace provided by the user and inserted lots more whitespace of their own, because they could not accurately
predict when extra spaces were needed to prevent accidental token pasting.
Optional argument when invoking rest argument macros: As an extension, GCC permits you to omit the variable arguments entirely when you use a
variable argument macro. This is forbidden by the 1999 C standard, and will provoke a pedantic warning with GCC 3.0. Previous versions accepted it
silently.
## swallowing preceding text in rest argument macros: Formerly, in a macro expansion, if ## appeared before a variable arguments parameter, and the
set of tokens specified for that argument in the macro invocation was empty, previous versions of CPP would back up and remove the preceding sequence
of non-whitespace characters (not the preceding token). This extension is in direct conflict with the 1999 C standard and has been drastically pared back.
In the current version of the preprocessor, if ## appears between a comma and a variable arguments parameter, and the variable argument is omitted
entirely, the comma will be removed from the expansion. If the variable argument is empty, or the token before ## is not a comma, then ## behaves as a
normal token paste.
#line and #include: The #line directive used to change GCC's notion of the "directory containing the current file," used by #include with a double-
quoted header file name. In 3.0 and later, it does not. See Line Control for further explanation.
Syntax of #line: In GCC 2.95 and previous, the string constant argument to #line was treated the same way as the argument to #include: backslash
escapes were not honored, and the string ended at the second ". This is not compliant with the C standard. In GCC 3.0, an attempt was made to correct
the behavior, so that the string was treated as a real string constant, but it turned out to be buggy. In 3.1, the bugs have been fixed. (We are not fixing
the bugs in 3.0 because they affect relatively few people and the fix is quite invasive.)
History
Copyright © 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
Copyright © 2000, 2001, 2002 Zeljko Juric, Sebastian Reichelt, Kevin Kofler
This part of the documentation is a modified version of the GNU Assembler Manual. Therefore it is licensed under the GNU Free Documentation License.
The GNU assembler as is primarily intended to assemble the output of the GNU C compiler for use by the linker, so it may be regarded as an internal part of
TIGCC package. However, it may be called as a standalone program, and the GNU team tried to make as assemble everything correctly that other assemblers
for the same machine would assemble. Any exceptions are documented explicitly. This doesn't mean as always uses the same syntax as other assemblers for
the same architecture; for example, there exist several incompatible versions of the MC 68000 assembly language syntax, so the syntax used in the GNU
assembler is not exactly the same as in some other assemblers (like the A68k Assembler, which is the most frequently used assembler for the TI-89 and TI-
92+, and which is also included in the TIGCC package as a standalone program).
This documentation will cover as features which are applicable to TIGCC. The most frequent use of as is probably as an inline assembler, which allows mixing
assembly statements with C code using the asm keyword.
This documentation is not intended as an introduction to programming in assembly language. In a similar vein, you will not find here details about machine
architecture: here you can not expect detailed description of the instruction set, standard mnemonics, registers or addressing modes. You may want to consult
the Motorola manufacturer's machine architecture manual for such information.
Note: It is possible to use source files for the GNU Assembler together with C source files in TIGCC projects.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version
published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is
included in the section entitled "GNU Free Documentation License".
After the program name as, the command line may contain options and file names. Options may appear in any order, and may be before, after, or between file
names. The order of file names is significant.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 102 of 173
-- (two hyphens) by itself names the standard input file explicitly, as one of the files for as to assemble.
Except for -- any command line argument that begins with a hyphen (-) is an option. Each option changes the behavior of as. No option changes the way
another option works. An option is a - followed by one or more letters; the case of the letter is important. All options are optional.
Some options expect exactly one file name to follow them. The file name may either immediately follow the option's letter (compatible with older assemblers)
or it may be the next command argument (GNU standard). These two command lines are equivalent:
as -o my-object-file.o mumble.s
as -omy-object-file.o mumble.s
If you are invoking as via tigcc, you can use the '-Wa' option to pass arguments through to the assembler. The assembler arguments must be separated from
each other (and the '-Wa') by commas. For example:
This passes two options to the assembler: '-alh' (emit a listing to standard output with high-level and assembly source) and '-L' (retain local symbols in the
symbol table).
Usually you do not need to use this '-Wa' mechanism, since many compiler command-line options are automatically passed to the assembler by the compiler.
(You can call the GNU compiler driver with the '-v' option to see precisely what options it passes to each compilation pass, including the assembler.)
-a[cdhlmns]
Turn on listings, in any of a variety of ways:
-ac
omit false conditionals
-ad
omit debugging directives
-ah
include high-level source
-al
include assembly
-am
include macro expansions
-an
omit forms processing
-as
include symbols
=file
set the name of the listing file
You may combine these options; for example, use '-aln' for assembly listing without forms processing. The '=file' option, if used, must be the last one.
By itself, '-a' defaults to '-ahls'.
--all-relocs
Output all references to non-absolute symbols in the assembled file as relocation items in the object file, even if the form of a reference would permit the
assembler to resolve it. This especially affects pc-relative references to symbols defined in the same section, and certain calculations with symbols. For
some calculations, this requires special TIGCC-specific support for negative relocation items, which makes object files unusable with older versions of
TIGCC. If a calculation cannot be output without being resolved, an error message is generated. This option implies '--keep-locals'. The assembler also
outputs a special symbol __ld_all_relocs to tell the linker that there are no implicit dependencies between different locations inside the sections.
-D
Ignored. This option is accepted for script compatibility with calls to other assemblers.
--defsym sym=value
Define the symbol sym to be value before assembling the input file. value must be an integer constant. As in C, a leading 0x indicates a hexadecimal
value, and a leading 0 indicates an octal value.
-f
"fast" - skip whitespace and comment preprocessing (assume source is compiler output).
This option should only be used when assembling programs written by a (trusted) compiler. It stops the assembler from doing whitespace and comment
preprocessing on the input file(s) before assembling them. See Preprocessing.
Warning: if you use '-f' when the files actually need to be preprocessed (if they contain comments, for example), as does not work correctly.
--gstabs
Generate stabs debugging information for each assembler line. This may help debugging assembler code, if the debugger can handle it.
--help
Print a summary of the command line options and exit.
--target-help
Print a summary of all target specific options and exit.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 103 of 173
-I dir
Add directory dir to the search list for .include directives.
-J
Don't warn about signed overflow.
-K
This option is accepted but has no effect on the 680x0 family.
-L
--keep-locals
Keep (in the symbol table) local symbols. On traditional a.out systems these start with L, but different systems have different local label prefixes. See
Including Local Labels.
--listing-lhs-width=number
Set the maximum width, in words, of the output data column for an assembler listing to number.
--listing-lhs-width2=number
Set the maximum width, in words, of the output data column for continuation lines in an assembler listing to number.
--listing-rhs-width=number
Set the maximum width of an input source line, as displayed in a listing, to number bytes.
--listing-cont-lines=number
Set the maximum number of lines printed in a listing for a single line of input to number+1.
-M
--mri
Use MRI compatibility mode. See Assembling in MRI Compatibility Mode.
--MD depfile
Generate a dependency file. This file consists of a single rule suitable for make describing the dependencies of the main source file. The rule is written to
the file named in its argument. This feature is used in the automatic updating of makefiles. It is not particulary useful for TIGCC.
-o objfile
Name the object-file output from as objfile. See Naming the Output File.
-R
Fold the data section into the text section. See Joining the Data and Text Sections.
--statistics
Print the maximum space (in bytes) and total time (in seconds) used by assembly.
--strip-local-absolute
Remove local absolute symbols from the outgoing symbol table.
--traditional-format
Use a more traditional output format. See Traditional Assembler Output Format.
-v
-version
Print the as version.
--version
Print the as version and exit.
-W
--no-warn
Suppress warning messages.
--fatal-warnings
Treat warnings as errors.
--warn
Don't suppress warning messages or treat them as errors.
-w
Ignored.
-x
Ignored.
-Z
Generate an object file even after errors.
-- | files
Standard input, or source files to assemble.
M680x0 Options
Enabling Listings
Naming the Object File
Controlling Warnings
Joining the Data and Text Sections
Including Local Labels
Traditional Assembler Output Format
Assembling in MRI Compatibility Mode
M680x0 Options
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 104 of 173
-l
You can use the '-l' option to shorten the size of references to undefined symbols. If you do not use the '-l' option, references to undefined symbols are
wide enough for a full long (32 bits). (Since as cannot know where these symbols end up, as can only allocate space for the linker to fill in later. Since as
does not know how far away these symbols are, it allocates as much space as it can.) If you use this option, the references are only one word wide (16
bits). This may be useful if you want the object file to be as small as possible, and you know that the relevant symbols are always less 32 KB away. This
option implies '--short-jumps'.
--short-jumps
The '--short-jumps' option shortens the size of branches to undefined symbols. Unlike '-l', other references to undefined symbols are kept wide enough
for a full long (32 bits), unless an explicit size is specified. This enables you to optimize a modular program that is smaller than 32 KB as well as possible,
while still being able to reference an external BSS or data section (since no jumps can point into these sections). Previously (and in non-TIGCC
assemblers), the '-l' option acted like this, but the documentation did not say this.
--register-prefix-optional
Since the compiler as configured for TIGCC does not prepend an underscore to the names of user variables, the assembler requires a % before any use of
a register name. This is intended to let the assembler distinguish between C variables and functions named a0 through a7, and so on. The '--register-
prefix-optional' option may be used to permit omitting the % even in TIGCC. If this is done, it will generally be impossible to refer to C variables and
functions with the same names as register names.
--bitwise-or
Normally the character | is treated as a comment character, which means that it can not be used in expressions. The '--bitwise-or' option turns | into a
normal character. In this mode, you must either use C style comments, or start comments with a # character at the beginning of a line.
--base-size-default-16
--base-size-default-32
If you use an addressing mode with a base register without specifying the size, as will normally use the full 32 bit value. For example, the addressing
mode %a0@(%d0) is equivalent to %a0@(%d0:l). You may use the '--base-size-default-16' option to tell as to default to using the 16 bit value. In this
case, %a0@(%d0) is equivalent to %a0@(%d0:w). You may use the '--base-size-default-32' option to restore the default behaviour.
--disp-size-default-16
--disp-size-default-32
If you use an addressing mode with a displacement, and the value of the displacement is not known, as will normally assume that the value is 32 bits. For
example, if the symbol disp has not been defined, as will assemble the addressing mode %a0@(disp,%d0) as though disp is a 32 bit value. You may use
the '--disp-size-default-16' option to tell as to instead assume that the displacement is 16 bits. In this case, as will assemble %a0@(disp,%d0) as
though disp is a 16 bit value. You may use the '--disp-size-default-32' option to restore the default behaviour.
--pcrel
Always keep branches PC-relative. In the M680x0 architecture all branches are defined as PC-relative. However, on some processors (including the
M68000 used in calculators) they are limited to word displacements maximum. When as needs a long branch that is not available, it normally emits an
absolute jump instead. This option disables this substitution. When this option is given and no long branches are available, only word branches will be
emitted. An error message will be generated if a word branch cannot reach its target. See Branch Improvement.
-m680x0
as can assemble code for several different members of the Motorola 680x0 family. The default in TIGCC is to assemble code for the 68000
microprocessor. The following options may be used to change the default. These options control which instructions and addressing modes are permitted.
The members of the 680x0 family are very similar. For detailed information about the differences, see the Motorola manuals. (These options are not very
useful for TIGCC.)
-m68000
-m68ec000
-m68hc000
-m68hc001
-m68008
-m68302
-m68306
-m68307
-m68322
-m68356
Assemble for the 68000. '-m68008', '-m68302', and so on are synonyms for '-m68000', since the chips are the same from the point of view of
the assembler.
-m68010
Assemble for the 68010.
-m68020
-m68ec020
Assemble for the 68020.
-m68030
-m68ec030
Assemble for the 68030.
-m68040
-m68ec040
Assemble for the 68040.
-m68060
-m68ec060
Assemble for the 68060.
-mcpu32
-m68330
-m68331
-m68332
-m68333
-m68334
-m68336
-m68340
-m68341
-m68349
-m68360
Assemble for the CPU32 family of chips.
-m5200
Assemble for the ColdFire family of chips.
-m68881
-m68882
Assemble 68881 floating point instructions. This is the default for the 68020, 68030, and the CPU32. The 68040 and 68060 always support floating
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 105 of 173
point instructions.
-mno-68881
Do not assemble 68881 floating point instructions. This is the default for 68000 and the 68010. The 68040 and 68060 always support floating point
instructions, even if this option is used.
-m68851
Assemble 68851 MMU instructions. This is the default for the 68020, 68030, and 68060. The 68040 accepts a somewhat different set of MMU
instructions; '-m68851' and '-m68040' should not be used together.
-mno-68851
Do not assemble 68851 MMU instructions. This is the default for the 68000, 68010, and the CPU32. The 68040 accepts a somewhat different set of
MMU instructions.
Enabling Listings
The options starting with '-a' enable listing output from the assembler. By itself, '-a' requests high-level, assembly, and symbols listing. You can use other
letters to select specific options for the list: '-ah' requests a high-level language listing, '-al' requests an output-program assembly listing, and '-as' requests a
symbol table listing. High-level listings require that a compiler debugging option like '-g' be used, and that assembly listings ('-al') be requested also.
Use the '-ac' option to omit false conditionals from a listing. Any lines which are not assembled because of a false .if (or .ifdef, or any other conditional), or
a true .if followed by an .else, will be omitted from the listing.
Use the '-ad' option to omit debugging directives from the listing.
Once you have specified one of these options, you can further control listing output and its appearance using the directives .list, .nolist, .psize, .eject,
.title, and .sbttl. The '-an' option turns off all forms processing. If you do not request listing output with one of the '-a' options, the listing-control
directives have no effect.
The letters after '-a' may be combined into one option, e.g., '-aln'.
Note if the assembler source is coming from the standard input (e.g. because it is being created by gcc and the '-pipe' command line switch is being used)
then the listing will not contain any comments or preprocessor directives. This is because the listing code buffers input source lines from stdin only after they
have been preprocessed by the assembler. This reduces memory usage and makes the code more efficient.
Enabling Listings
The listing feature of the assembler can be enabled via the command line switch '-a' (see Enabling Listings). This feature combines the input source file(s) with
a hex dump of the corresponding locations in the output object file, and displays them as a listing file. The format of this listing can be controlled by pseudo ops
inside the assembler source (see Enabling Listings for details) and also by the following switches:
--listing-lhs-width=number
Sets the maximum width, in words, of the first line of the hex byte dump. This dump appears on the left hand side of the listing output.
--listing-lhs-width2=number
Sets the maximum width, in words, of any further lines of the hex byte dump for a given input source line. If this value is not specified, it defaults to
being the same as the value specified for '--listing-lhs-width'. If neither switch is used the default is to one.
--listing-rhs-width=number
Sets the maximum width, in characters, of the source line that is displayed alongside the hex dump. The default value for this parameter is 100. The
source line is displayed on the right hand side of the listing output.
--listing-cont-lines=number
Sets the maximum number of continuation lines of hex dump that will be displayed for a given single line of source input. The default value is 4.
There is always one object file output when you run as. By default it has the name a.out. You can use the '-o' option (which takes exactly one filename) to
give the object file a different name.
Whatever the object file is called, as overwrites any existing file of the same name.
Controlling Warnings
as should never give a warning or error message when assembling compiler output. But programs written by people often cause as to give a warning that a
particular assumption was made. All such warnings are directed to the standard error file.
If you use the '-W' and '--no-warn' options, no warnings are issued. This only affects the warning messages: it does not change any particular of how as
assembles your file. Errors, which stop the assembly, are still reported.
If you use the '--fatal-warnings' option, as considers files that generate warnings to be in error.
You can switch these options off again by specifying '--warn', which causes warnings to be output as usual.
The '-R' option tells as to write the object file as if all data-section data lives in the text section. This is only done at the very last moment: your binary data are
the same, but data section parts are relocated differently. The data section part of your object file is zero bytes long because all its bytes are appended to the
text section. (see Sections and Relocation).
When you specify '-R', it would be possible to generate shorter address displacements (because we do not have to cross between text and data section). We
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 106 of 173
refrain from doing this simply for compatibility with older versions of as. In the future, '-R' may work this way.
When as is configured for COFF output (which is the case in TIGCC), this option is only useful if you use sections named .text and .data.
Labels beginning with L (upper case only) are called local labels. See Symbol Names. Normally you do not see such labels when debugging, because they are
intended for the use of programs (like compilers) that compose assembler programs, not for your notice. Normally both as and ld discard such labels, so you
do not normally debug with them.
The '-L' option tells as to retain those L... symbols in the object file. Usually, if you do this, you also tell the linker ld to preserve symbols whose names begin
with L.
By default, a local label is any label beginning with L, but each target is allowed to redefine the local label prefix.
For some targets, the output of as is different in some ways from the output of some existing assembler. The '--traditional-format' switch requests as to use
the traditional format instead.
For example, it disables the exception frame optimizations which as normally does by default on gcc output.
The '-M' or '--mri' option selects MRI compatibility mode. This changes the syntax and pseudo-op handling of as to make it compatible with the ASM68K
assembler from Microtec Research. The exact nature of the MRI syntax will not be documented here; see the MRI manuals for more information. Note in
particular that the handling of macros and macro arguments is somewhat different. The purpose of this option is to permit assembling existing MRI assembler
code using as.
The MRI compatibility is not complete. Certain operations of the MRI assembler depend upon its object file format, and can not be supported using other object
file formats. Supporting these would require enhancing each object file format individually. These are:
global symbols in common section The m68k MRI assembler supports common sections which are merged by the linker. Other object file formats do not
support this. as handles common sections by treating them as a single common symbol. It permits local symbols to be defined within a common section,
but it can not support global symbols, since it has no way to describe them.
complex relocations The MRI assemblers support relocations against a negated section address, and relocations which combine the start addresses of two
or more sections. These are not support by other object file formats.
END pseudo-op specifying start address The MRI END pseudo-op permits the specification of a start address. This is not supported by other object file
formats. The start address may instead be specified using the '-e' option to the linker, or in a linker script.
IDNT, .ident and NAME pseudo-ops The MRI IDNT, .ident and NAME pseudo-ops assign a module name to the output file. This is not supported by other
object file formats.
ORG pseudo-op The m68k MRI ORG pseudo-op begins an absolute section at a given address. This differs from the usual as .org pseudo-op, which
changes the location within the current section. Absolute sections are not supported by other object file formats. The address of a section may be
assigned within a linker script.
There are some other features of the MRI assembler which are not supported by as, typically either because they are difficult or because they seem of little
consequence. Some of these may be supported in future releases.
packed binary coded decimal Packed binary coded decimal is not supported. This means that the DC.P and DCB.P pseudo-ops are not supported.
OPT branch control options The m68k OPT branch control options - B, BRS, BRB, BRL, and BRW - are ignored. as automatically relaxes all branches, whether
forward or backward, to an appropriate size, so these options serve no purpose.
OPT list control options The following m68k OPT list control options are ignored: C, CEX, CL, CRE, E, G, I, M, MEX, MC, MD, X.
other OPT options The following m68k OPT options are ignored: NEST, O, OLD, OP, P, PCO, PCR, PCS, R.
OPT D option is default The m68k OPT D option is the default, unlike the MRI assembler. OPT NOD may be used to turn it off.
.list pseudo-op. The various options of the i960 .list pseudo-op are not supported.
Input Files
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 107 of 173
Input Files
We use the phrase source program, abbreviated source, to describe the program input to one run of as. The program may be in one or more files; how the
source is partitioned into files doesn't change the meaning of the source.
The source program is a concatenation of the text in all the files, in the order specified.
Each time you run as it assembles exactly one source program. The source program is made up of one or more files. (The standard input is also a file.)
You give as a command line that has zero or more input file names. The input files are read (from left file name to right). A command line argument (in any
position) that has no special meaning is taken to be an input file name.
If you give as no file names it attempts to read one input file from the as standard input, which is normally your terminal. You may have to type Ctrl-D to tell
as there is no more program to assemble.
Use -- if you need to explicitly name the standard input file in your command line.
Input Files
There are two ways of locating a line in the input file (or files) and either may be used in reporting error messages. One way refers to a line number in a
physical file; the other refers to a line number in a "logical" file. See Error and Warning Messages.
Physical files are those files named in the command line given to as.
Logical files are simply names declared explicitly by assembler directives; they bear no relation to physical files. Logical file names help error messages reflect
the original source file, when as source is itself synthesized from other files. as understands the # directives emitted by the gcc preprocessor. See also .file.
Every time you run as, it produces an output file, which is your assembly language program translated into numbers. This file is the object file. Its default name
is a.out. You can give it another name by using the '-o' option. Conventionally, object file names end with .o. The default name is used for historical reasons:
older assemblers were capable of assembling self-contained programs directly into a runnable program. (For some formats, this isn't currently possible, but it
can be done for the a.out format.)
The object file is meant for input to the linker ld. It contains assembled program code, information to help ld integrate the assembled program into a runnable
file, and (optionally) symbolic information for the debugger.
as may write warnings and error messages to the standard error file (usually your terminal). This should not happen when a compiler runs as automatically.
Warnings report an assumption made so that as could keep assembling a flawed program; errors report a grave problem that stops the assembly.
(where NNN is a line number). If a logical file name has been given (see .file) it is used for the filename, otherwise the name of the current input file is used.
If a logical line number was given (see .line) then it is used to calculate the number printed, otherwise the actual line in the current source file is printed. The
message text is intended to be self explanatory (in the grand Unix tradition).
The file name and line number are derived as for warning messages. The actual message text may be rather less explanatory because many of them aren't
supposed to happen.
The machine-independent syntax used by the GNU assembler is similar to what many other assemblers use; it is inspired by the BSD 4.2 assembler. Motorola-
specific features are explained at the end of this chapter.
Preprocessing
Whitespace
Comments
Symbols
Statements
Constants
Motorola 680x0 Dependent Features
Preprocessing
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 108 of 173
adjusts and removes extra whitespace. It leaves one space or tab before the keywords on a line, and turns any other whitespace on the line into a single
space.
removes all comments, replacing them with a single space, or an appropriate number of newlines.
It does not do macro processing, include file handling, or anything else you may get from your C compiler's preprocessor. You can do include file processing
with the .include directive (see .include). You can use the GNU C compiler driver to get other "CPP" style preprocessing by giving the input file a .S suffix.
See Options Controlling the Kind of Output, gcc.info, Using GNU CC.
Excess whitespace, comments, and character constants cannot be used in the portions of the input text that are not preprocessed.
If the first line of an input file is #NO_APP or if you use the '-f' option, whitespace and comments are not removed from the input file. Within an input file, you
can ask for whitespace and comment removal in specific portions of the by putting a line that says #APP before the text that may contain whitespace or
comments, and putting a line that says #NO_APP after this text. This feature is mainly intend to support asm statements in compilers whose output is otherwise
free of comments and whitespace.
Whitespace
Whitespace is one or more blanks or tabs, in any order. Whitespace is used to separate symbols, and to make programs neater for people to read. Unless within
character constants (see Character Constants), any whitespace means the same as exactly one space.
Comments
There are two ways of rendering comments to as. In both cases the comment is equivalent to one space.
Anything from /* through the next */ is a comment. This means you may not nest these comments.
/*
The only way to include a newline ('\n') in a comment
is to use this sort of comment.
*/
Anything from the line comment character to the next newline is considered a comment and is ignored. The line comment character is | on the 680x0 family of
processors.
To be compatible with past assemblers, lines that begin with # have a special interpretation. Following the # should be an absolute expression (see
Expressions): the logical line number of the next line. Then a string (see Strings) is allowed: if present it is a new logical file name. The rest of the line, if any,
should be whitespace.
If the first non-whitespace characters on the line are not numeric, the line is ignored. (Just like a comment.)
This feature is deprecated, and may disappear from future versions of as.
Symbols
A symbol is one or more characters chosen from the set of all letters (both upper and lower case), digits and the three characters _.$. No symbol may begin
with a digit. Case is significant. There is no length limit: all characters are significant. Symbols are delimited by characters not in that set, or by the beginning of
a file (since the source program must end with a newline, the end of a file is not a possible symbol delimiter). See Symbols.
Statements
A statement ends at a newline character (\n) or at a semicolon (;). The newline or semicolon is considered part of the preceding statement. Newlines and
semicolons within character constants are an exception: they do not end statements.
It is an error to end any statement with end-of-file: the last character of any input file should be a newline. An empty statement is allowed, and may include
whitespace. It is ignored.
A statement begins with zero or more labels, optionally followed by a key symbol which determines what kind of statement it is. The key symbol determines the
syntax of the rest of the statement. If the symbol begins with a dot . then the statement is an assembler directive: typically valid for any computer. If the
symbol begins with a letter the statement is an assembly language instruction: it assembles into a machine language instruction. A label is a symbol
immediately followed by a colon (:). Whitespace before a label or after a colon is permitted, but you may not have whitespace between a label's symbol and its
colon. See Labels.
Constants
A constant is a number, written so that its value is known by inspection, without knowing any context. Like this:
.byte 74, 0112, 092, 0x4A, 0X4a, 'J, '\J # All the same value.
.ascii "Ring the bell\7" # A string constant.
.octa 0x123456789abcdef0123456789ABCDEF0 # A bignum.
.float 0f-314159265358979323846264338327\
95028841971.693993751E-40 # - pi, a flonum.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 109 of 173
Character Constants
Number Constants
Character Constants
Constants Next
There are two kinds of character constants. A character stands for one character in one byte and its value may be used in numeric expressions. String constants
(properly called string literals) are potentially many bytes and their values may not be used in arithmetic expressions.
Strings
Characters
Strings
A string is written between double-quotes. It may contain double-quotes or null characters. The way to get special characters into a string is to escape these
characters: precede them with a backslash \ character. For example \\ represents one backslash: the first \ is an escape which tells as to interpret the second
character literally as a backslash (which prevents as from recognizing the second \ as an escape character). The complete list of escapes follows.
\b
Mnemonic for backspace; for ASCII this is octal code 010.
\f
Mnemonic for FormFeed; for ASCII this is octal code 014.
\n
Mnemonic for newline; for ASCII this is octal code 012.
\r
Mnemonic for carriage-Return; for ASCII this is octal code 015.
\t
Mnemonic for horizontal Tab; for ASCII this is octal code 011.
\x hex-digits...
A hex character code. All trailing hex digits are combined. Either upper or lower case x works.
\\
Represents one \ character.
\"
Represents one " character. Needed in strings to represent this character, because an unescaped " would end the string.
\ anything-else
Any other character when escaped by \ gives a warning, but assembles as if the \ was not present. The idea is that if you used an escape sequence you
clearly didn't want the literal interpretation of the following character. However as has no other interpretation, so as knows it is giving you the wrong
code and warns you of the fact.
Which characters are escapable, and what those escapes represent, varies widely among assemblers. The current set is what we think the BSD 4.2 assembler
recognizes, and is a subset of what most C compilers recognize. If you are in doubt, do not use an escape sequence.
Characters
A single character may be written as a single quote immediately followed by that character. The same escapes apply to characters as to strings. So if you want
to write the character backslash, you must write '\\ where the first \ escapes the second \. As you can see, the quote is an acute accent, not a grave accent. A
newline (or semicolon ;) immediately following an acute accent is taken as a literal character and does not count as the end of a statement. The value of a
character constant in a numeric expression is the machine's byte-wide code for that character. as assumes your character code is ASCII: 'A means 65, 'B
means 66, and so on.
Number Constants
Previous Constants
as distinguishes three kinds of numbers according to how they are stored in the target machine. Integers are numbers that would fit into an int in the C
language. Bignums are integers, but they are stored in more than 32 bits. Flonums are floating point numbers, described below.
Integers
Bignums
Flonums
Integers
A decimal integer starts with a non-zero digit followed by zero or more digits (0123456789).
A hexadecimal integer is 0x or 0X followed by one or more hexadecimal digits chosen from 0123456789abcdefABCDEF.
Integers have the usual values. To denote a negative integer, use the prefix operator - discussed under expressions (see Prefix Operators).
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 110 of 173
Bignums
A bignum has the same syntax and semantics as an integer except that the number (or its negative) takes more than 32 bits to represent in binary. The
distinction is made because in some places integers are permitted while bignums are not.
Flonums
A flonum represents a floating point number. The translation is indirect: a decimal floating point number from the text is converted by as to a generic binary
floating point number of more than sufficient precision. This generic floating point number is converted to a particular computer's floating point format (or
formats) by a portion of as specialized to that computer. The version of as used by TIGCC does not use TI's SMAP II BCD format; it emits standard IEEE
floating point numbers. It would be pointless to implement the correct behavior, since the appropriate numbers are easy to write, and converting between base
2 and 10 can decrease precision.
The digit 0.
At least one of the integer part or the fractional part must be present. The floating point number has the usual base-10 value.
as does all processing using integers. Flonums are computed independently of any floating point hardware in the computer running as.
In this configuration of as (which does not prepend an underscore to the names of user variables), the assembler requires a '%' before any use of a register
name. This is intended to let the assembler distinguish between C variables and functions named 'a0' through 'a7', and so on.
Two different syntaxes for the Motorola 680x0 are widely used. The first one was developed at MIT. The second one is the standard Motorola syntax for this
chip, and it differs from the MIT syntax. as can accept Motorola syntax for operands, even if MIT syntax is used for other operands in the same instruction. The
two kinds of syntax are fully compatible.
MIT Syntax
Motorola Syntax
Branch Improvement
Special Characters
MIT Syntax
The MIT syntax uses instructions names and syntax compatible with the Sun assembler. Intervening periods are ignored; for example, movl is equivalent to
mov.l.
In the following table, apc stands for any of the address registers (%a0 through %a7), the program counter (%pc), the zero-address relative to the program
counter (%zpc), a suppressed address register (%za0 through %za7), or it may be omitted entirely. The use of size means one of w or l, and it may be omitted,
along with the leading colon, unless a scale is also specified. The use of scale means one of 1, 2, 4, or 8, and it may always be omitted along with the leading
colon.
The following addressing modes are understood (note that some of them are valid only on 68020 or later processors, not on the ordinary 68000 used in TI
calculators):
Immediate
#number
Data Register
%d0 through %d7
Address Register
%a0 through %a7
%a7 is also known as %sp, i.e. the Stack Pointer. %a6 is also known as %fp, the Frame Pointer.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 111 of 173
Index
apc@(number,register:size:scale)
Postindex
apc@(number)@(onumber,register:size:scale)
Preindex
apc@(number,register:size:scale)@(onumber)
The number may be omitted. Omitting the register produces the Postindex addressing mode.
Absolute
symbol, or digits, optionally followed by :b, :w, or :l.
Motorola Syntax
In the following table, apc stands for any of the address registers (%a0 through %a7), the program counter (%pc), the zero-address relative to the program
counter (%zpc), or a suppressed address register (%za0 through %za7). The use of size means one of w or l, and it may always be omitted along with the
leading dot. The use of scale means one of 1, 2, 4, or 8, and it may always be omitted along with the leading asterisk.
The following additional addressing modes are understood (note that some of them are valid only on 68020 or later processors, not on the ordinary 68000 used
in TI calculators):
The number may also appear within the parentheses, as in (number,%a0). When used with the pc, the number may be omitted (with an address register,
omitting the number produces Address Register Indirect mode).
Index
number(apc,register.size*scale)
The number may be omitted, or it may appear within the parentheses. The apc may be omitted. The register and the apc may appear in either order. If
both apc and register are address registers, and the size and scale are omitted, then the first register is taken as the base register, and the second as the
index register.
Postindex
([number,apc],register.size*scale,onumber)
The onumber, or the register, or both, may be omitted. Either the number or the apc may be omitted, but not both.
Preindex
([number,apc,register.size*scale],onumber)
The number, or the apc, or the register, or any two of them, may be omitted. The onumber may be omitted. The register and the apc may appear in
either order. If both apc and register are address registers, and the size and scale are omitted, then the first register is taken as the base register, and
the second as the index register.
Branch Improvement
Certain pseudo opcodes are permitted for branch instructions. They expand to the shortest branch instruction that reach the target. Generally these mnemonics
are made by substituting j for b at the start of a Motorola mnemonic.
The following table summarizes the pseudo-operations for the 68000 processor; the 68020 has some more possibilites. Note that the 68000 LONG operations
are always absolute and require runtime relocation. They will not be used if the '--pcrel' option is given. A (*) flags cases that are more fully described after
the table:
Displacement
XX: condition
NX: negative of condition XX
jbsr
jra
These are the simplest jump pseudo-operations; they always map to one particular machine instruction, depending on the displacement to the branch
target. This instruction will be a byte or word branch if that is sufficient. Otherwise, if the '--pcrel' option is not given, an absolute long jump will be
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 112 of 173
emitted. If the '--pcrel' option is given and a word branch cannot reach the target, an error message is generated.
In addition to standard branch operands, as allows these pseudo-operations to have all operands that are allowed for jsr and jmp, substituting these
instructions if the operand given is not valid for a branch instruction.
jXX
Here, jXX stands for an entire family of pseudo-operations, where XX is a conditional branch or condition-code test. The full list of pseudo-ops in this
family is:
Usually, each of these pseudo-operations expands to a single branch instruction. However, if a word branch is not sufficient and the '--pcrel' option is not
given, as issues a longer code fragment in terms of NX, the opposite condition to XX. For example, under these conditions:
jXX foo
gives
bNXs oof
jmp foo
oof:
dbXX
The full family of pseudo-operations covered here is:
Motorola dbXX instructions allow word displacements only. When a word displacement is sufficient, each of these pseudo-operations expands to the
corresponding Motorola instruction. When a word displacement is not sufficient and long branches are available, when the source reads dbXX foo, as
emits
dbXX oo1
bra.s oo2
oo1: jmp foo
oo2:
Special Characters
The immediate character is # for Sun compatibility. The line-comment character is | (unless the '--bitwise-or' option is used). If a # appears at the beginning
of a line, it is treated as a comment unless it looks like # line file, in which case it is treated normally.
Roughly, a section is a range of addresses, with no gaps; all data "in" those addresses is treated the same for some particular purpose. For example there may
be a "read only" section.
The linker ld reads many object files (partial programs) and combines their contents to form a runnable program. When as emits an object file, the partial
program is assumed to start at address 0. ld assigns the final addresses for the partial program, so that different partial programs do not overlap. This is
actually an oversimplification, but it suffices to explain how as uses sections.
ld moves blocks of bytes of your program to their run-time addresses. These blocks slide to their run-time addresses as rigid units; their length does not
change and neither does the order of bytes within them. Such a rigid unit is called a section. Assigning run-time addresses to sections is called relocation. It
includes the task of adjusting mentions of object-file addresses so they refer to the proper run-time addresses.
An object file written by as has at least three sections, any of which may be empty. These are named text, data and bss sections.
as can also generate whatever other named sections you specify using the .section directive. If you do not use any directives that place output in the .text
or .data sections, these sections still exist, but are empty. Within the object file, the text section starts at address 0, the data section follows, and the bss
section follows the data section.
To let ld know which data changes when the sections are relocated, and how to change that data, as also writes to the object file details of the relocation
needed. To perform relocation ld must know, each time an address in the object file is mentioned:
Which section does the address refer to? What is the numeric value of (address) - (start-address of section)?
In fact, every address as ever uses is expressed as (section) + (offset into section)
Further, most expressions as computes have this section-relative nature. In this manual we use the notation {secname N} to mean "offset N into section
secname."
Apart from text, data and bss sections you need to know about the absolute section. When ld mixes partial programs, addresses in the absolute section remain
unchanged. For example, address {absolute 0} is "relocated" to run-time address 0 by ld. Although the linker never arranges two partial programs' data
sections with overlapping addresses after linking, by definition their absolute sections must overlap. Address {absolute 239} in one part of a program is
always the same address when the program is running as address {absolute 239} in any other part of the program.
The idea of sections is extended to the undefined section. Any address whose section is unknown at assembly time is by definition rendered {undefined U} -
where U is filled in later. Since numbers are always defined, the only way to generate an undefined address is to mention an undefined symbol. A reference to a
named common block would be such a symbol: its value is unknown at assembly time so it has section undefined.
By analogy the word section is used to describe groups of sections in the linked program. ld puts all partial programs' text sections in contiguous addresses in
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 113 of 173
the linked program. It is customary to refer to the text section of a program, meaning all the addresses of all partial programs' text sections. Likewise for data
and bss sections.
Some sections are manipulated by ld; others are invented for use of as and have no meaning except during assembly.
Linker Sections
Assembler Internal Sections
Sub-Sections
bss Section
Linker Sections
These sections hold your program. as and ld treat them as separate but equal sections. Anything you can say of one section is true of another. When the
program is running, however, it is customary for the text section to be unalterable. The text section is often shared among processes: it contains instructions,
constants and the like. The data section of a running program is usually alterable: for example, C variables would be stored in the data section.
bss section
This section contains zeroed bytes when your program begins running. It is used to hold uninitialized variables or common storage. The length of each
partial program's bss section is important, but because it starts out containing zeroed bytes there is no need to store explicit zero bytes in the object file.
The bss section was invented to eliminate those explicit zeros from object files.
absolute section
Address 0 of this section is always "relocated" to runtime address 0. This is useful if you want to refer to an address that ld must not change when
relocating. In this sense we speak of absolute addresses being "unrelocatable": they do not change during relocation.
undefined section
This "section" is a catch-all for address references to objects not in the preceding sections.
An idealized example of three relocatable sections follows. Memory addresses are on the horizontal axis.
+ - --+ - -+--+
partial program # 1: |ttttt|dddd|00|
+ - --+ - -+--+
+ - + - + - +
partial program # 2: |TTT|DDD|000|
+ - + - + - +
addresses: 0 ...
These sections are meant only for the internal use of as. They have no meaning at run-time. You do not really need to know about these sections for most
purposes; but they can be mentioned in as warning messages, so it might be helpful to have an idea of their meanings to as. These sections are used to permit
the value of every expression in your assembly language program to be a section-relative address.
ASSEMBLER-INTERNAL-LOGIC-ERROR!
An internal assembler logic error has been found. This means there is a bug in the assembler.
expr section
The assembler stores complex expression internally as combinations of symbols. When it needs to represent an expression as a symbol, it puts it in the
expr section.
Sub-Sections
You may have separate groups of data in named sections that you want to end up near to each other in the object file, even though they are not contiguous in
the assembler source. as allows you to use subsections for this purpose. Within each section, there can be numbered subsections with values from 0 to 8192.
Objects assembled into the same subsection go into the object file together with other objects in the same subsection. For example, a compiler might want to
store constants in the text section, but might not want to have them interspersed with the program being assembled. In this case, the compiler could issue
a .text 0 before each section of code being output, and a .text 1 before each group of constants being output.
Subsections are optional. If you do not use subsections, everything goes in subsection number zero.
Subsections appear in your object file in numeric order, lowest numbered to highest. (All this to be compatible with other people's assemblers.) The object file
contains no representation of subsections; ld and other programs that manipulate object files see no trace of them. They just see all your text subsections as a
text section, and all your data subsections as a data section.
To specify which subsection you want subsequent statements assembled into, use a numeric argument to specify it, in a .text expression or a .data
expression statement. You can also use an extra subsection argument with arbitrarily named sections: .section name, expression. Expression should be an
absolute expression. (see Expressions.) If you just say .text then .text 0 is assumed. Likewise .data means .data 0. Assembly begins in text 0. For
instance:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 114 of 173
Each section has a location counter incremented by one for every byte assembled into that section. Because subsections are merely a convenience restricted to
as there is no concept of a subsection location counter. There is no way to directly manipulate a location counter - but the .align directive changes it, and any
label definition captures its current value. The location counter of the section where statements are being assembled is said to be the active location counter.
bss Section
The bss section is used for local common variable storage. You may allocate address space in the bss section, but you may not dictate data to load into it before
your program executes. When your program starts running, all the contents of the bss section are zeroed bytes.
The .comm pseudo-op may be used to declare a common symbol, which is another form of uninitialized symbol.
You may switch into the .bss section and define symbols as usual (see .section). You may only assemble zero values into the section. Typically the section
will only contain symbol definitions and .skip directives.
Assembler Symbols
Symbols are a central concept: the programmer uses symbols to name things, the linker uses symbols to link, and the debugger uses symbols to debug.
Note that as does not place symbols in the object file in the same order they were declared. This may break some debuggers.
Labels
Giving Symbols Other Values
Symbol Names
The Special Dot Symbol
Symbol Attributes
Labels
A label is written as a symbol immediately followed by a colon :. The symbol then represents the current value of the active location counter, and is, for
example, a suitable instruction operand. You are warned if you use the same symbol to represent two different locations: the first definition overrides any other
definitions.
A symbol can be given an arbitrary value by writing a symbol, followed by an equals sign =, followed by an expression (see Expressions). This is equivalent to
using the .set directive.
Symbol Names
Symbol names begin with a letter or with ., _, or $. That character may be followed by any string of digits, letters, dollar signs, and underscores. Case of
letters is significant: foo is a different symbol name than Foo.
Each symbol has exactly one name. Each name in an assembly language program refers to exactly one symbol. You may use that symbol name any number of
times in a program.
Local symbols help compilers and programmers use names temporarily. They create symbols which are guaranteed to be unique over the entire scope of the
input source code and which can be referred to by a simple notation. To define a local symbol, write a label of the form N: (where N represents any positive
integer). To refer to the most recent previous definition of that symbol write Nb, using the same number as when you defined the label. To refer to the next
definition of a local label, write Nf - The b stands for "backwards" and the f stands for "forwards".
There is no restriction on how you can use these labels, and you can reuse them as well. So it is possible to repeatedly define the same local label (using the
same number N), although you can only refer to the most recently defined local label of that number (for a backwards reference) or the next definition of a
specific local label for a forward reference. It is also worth noting that the first 10 local labels (0:...9:) are implemented in a slightly more efficient manner than
the others.
Here is an example:
1: jra 1f
2: jra 1b
1: jra 2f
2: jra 1b
Local symbol names are only a notational device. They are immediately transformed into more conventional symbol names before the assembler uses them.
The symbol names stored in the symbol table, appearing in error messages and optionally emitted to the object file. The names are constructed using these
parts:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 115 of 173
All local labels begin with L. Normally both as and ld forget symbols that start with L. These labels are used for symbols you are never intended to see. If
you use the '-L' option, as retains these symbols in the object file. If you also instruct ld to retain these symbols, you may use them in debugging.
N
This is the number that was used in the local label definition. So if the label is written 55:, the number is 55.
\002
This unusual character is included so you do not accidentally invent a symbol of the same name.
ordinal number
This is a serial number to keep the labels distinct. The first definition of 0: gets the number 1. The 15th definition of 0: gets the number 15, and so on.
Likewise the first definition of 1: gets the number 1 and its 15th defintion gets 15 as well.
as also supports an even more local form of local labels called dollar labels. These labels go out of scope (i.e. they become undefined) as soon as a non-local
label is defined. Thus they remain valid for only a small region of the input source code. Normal local labels, by contrast, remain in scope for the entire file, or
until they are redefined by another occurrence of the same local label.
Dollar labels are defined in exactly the same way as ordinary local labels, except that instead of being terminated by a colon, they are terminated by a dollar
sign (for example, 55$).
They can also be distinguished from ordinary local labels by their transformed name which uses ASCII character \001 (control-A) as the magic character to
distinguish them from ordinary labels.
The special symbol . refers to the current address that as is assembling into. Thus, the expression melvin: .long . defines melvin to contain its own address.
Assigning a value to . is treated the same as a .org directive. Thus, the expression .=.+4 is the same as saying .space 4.
Symbol Attributes
Every symbol has, as well as its name, the attributes "Value" and "Type". Depending on output format, symbols can also have auxiliary attributes. If you use a
symbol without defining it, as assumes zero for all these attributes, and probably won't warn you. This makes the symbol an externally defined symbol, which is
generally what you would want.
Value
Type
Symbol Attributes for COFF
Value
The value of a symbol is (usually) 32 bits. For a symbol which labels a location in the text, data, bss or absolute sections the value is the number of addresses
from the start of that section to the label. Naturally for text, data and bss sections the value of a symbol changes as ld changes section base addresses during
linking. Absolute symbols' values do not change during linking: that is why they are called absolute.
The value of an undefined symbol is treated in a special way. If it is 0 then the symbol is not defined in this assembler source file, and ld tries to determine its
value from other files linked into the same program. You make this kind of symbol simply by mentioning a symbol name without defining it. A non-zero value
represents a .comm common declaration. The value is how much common storage to reserve, in bytes (addresses). The symbol refers to the first address of the
allocated storage.
Type
The type attribute of a symbol contains relocation (section) information, any flag settings indicating that a symbol is external, and (optionally), other
information for linkers and debuggers. The exact format depends on the object-code output format in use.
The COFF format supports a multitude of auxiliary symbol attributes; like the primary symbol attributes, they are set between .def and .endef directives.
Primary Attributes
Auxiliary Attributes
Primary Attributes
The symbol name is set with .def; the value and type, respectively, with .val and .type.
Auxiliary Attributes
The as directives .dim, .line, .scl, .size, and .tag can generate auxiliary symbol table information for COFF.
Assembler Expressions
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 116 of 173
An expression specifies an address or numeric value. Whitespace may precede and/or follow an expression.
The result of an expression must be an absolute number, or else an offset into a particular section. If an expression is not absolute, and there is not enough
information when as sees the expression to know its section, a second pass over the source program might be necessary to interpret the expression - but the
second pass is currently not implemented. as aborts with an error message in this situation.
Empty Expressions
Integer Expressions
Empty Expressions
An empty expression has no value: it is just whitespace or null. Wherever an absolute expression is required, you may omit the expression, and as assumes a
value of (absolute) 0. This is compatible with other assemblers.
Integer Expressions
Arguments
Operators
Arguments
Arguments are symbols, numbers or subexpressions. In other contexts arguments are sometimes called "arithmetic operands". In this manual, to avoid
confusing them with the "instruction operands" of the machine language, we use the term "argument" to refer to parts of expressions only, reserving the word
"operand" to refer only to machine instruction operands.
Symbols are evaluated to yield {section NNN} where section is one of text, data, bss, absolute, or undefined. NNN is a signed, 2's complement 32 bit integer.
Numbers are usually integers. In principle, a number can be a flonum or bignum. In this case, you are warned that only the low order 32 bits are used, and as
pretends these 32 bits are an integer. You may write integer-manipulating instructions that act on exotic constants, compatible with other assemblers.
Subexpressions are a left parenthesis ( followed by an integer expression, followed by a right parenthesis ); or a prefix operator followed by an argument.
Operators
Operators are arithmetic functions, like + or %. Prefix operators are followed by an argument. Infix operators appear between their arguments. Operators may
be preceded and/or followed by whitespace.
Prefix Operators
Infix Operators
Prefix Operators
Operators Next
as has the following prefix operators. They each take one argument, which must be absolute.
-
Negation. Two's complement negation.
~
Complementation. Bitwise NOT.
Infix Operators
Previous Operators
Infix operators take two arguments, one on either side. Operators have precedence, but operations with equal precedence are performed left to right. Apart
from + or -, both arguments must be absolute, and the result is absolute.
1. Highest Precedence
*
Multiplication.
/
Division. Truncation is the same as the C operator /.
%
Remainder.
<
<<
Shift Left. Same as the C operator <<.
>
>>
Shift Right. Same as the C operator >>.
2. Intermediate precedence
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 117 of 173
&
Bitwise AND.
^
Bitwise Exclusive OR.
!
Bitwise OR NOT.
3. Low Precedence
+
Addition. If either argument is absolute, the result has the section of the other argument. You may not add together arguments from different
sections.
-
Subtraction. If the right argument is absolute, the result has the section of the left argument. If both arguments are in the same section, the result
is absolute. You may not subtract arguments from different sections.
==
Is Equal To.
<>
Is Not Equal To.
<
Is Less Than.
>
Is Greater Than.
>=
Is Greater Than Or Equal To.
<=
Is Less Than Or Equal To.
The comparison operators can be used as infix operators. A true results has a value of -1 whereas a false result has a value of 0. Note, these
operators perform signed comparisons.
4.
&&
Logical AND.
||
Logical OR.
These two logical operations can be used to combine the results of sub expressions. Note, unlike the comparison operators a true result returns a
value of 1. Also note that the logical OR operator has a slightly lower precedence than logical AND.
In short, it's only meaningful to add or subtract the offsets in an address; you can only have a defined section in one of the two arguments.
Assembler Directives
All assembler directives have names that begin with a period (.). The rest of the name is letters, usually in lower case.
This chapter mostly discusses directives that are available regardless of the target machine configuration for the GNU assembler.
.abort
.align
.ascii
.asciz
.balign[wl]
.byte
.comm
.data
.def
.dim
.double
.eject
.else
.end
.elseif
.endef
.endfunc
.endif
.endm
.endr
.equ
.equiv
.err
.even
.exitm
.extern
.fail
.file
.fill
.float
.func
.global
.hword
.ident
.if
.include
.incbin
.int
.irp
.irpc
.lcomm
.lflags
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 118 of 173
.line
.ln
.list
.long
.macro
.mri
.nolist
.octa
.org
.p2align[wl]
.print
.psize
.purgem
.quad
.rept
.sbttl
.scl
.section
.set
.short
.single
.size
.sleb128
.skip
.space
.stabd
.stabn
.stabs
.string
.struct
.tag
.text
.title
.type
.uleb128
.val
.vtable_entry
.word
.abort
This directive stops the assembly immediately. It is for compatibility with other assemblers. The original idea was that the assembly language source would be
piped into the assembler. If the sender of the source quit, it could use this directive to tell as to quit also. One day .abort will not be supported.
.align
Pad the location counter (in the current subsection) to a particular storage boundary. alignment (which must be absolute) is the alignment required, as
described below.
fill (also absolute) gives the fill value to be stored in the padding bytes. It (and the comma) may be omitted. If it is omitted, the padding bytes are normally
zero. However, on some systems, if the section is marked as containing code and the fill value is omitted, the space is filled with no-op instructions (I didn't
checked whether this is the case in TIGCC).
max is also absolute, and is also optional. If it is present, it is the maximum number of bytes that should be skipped by this alignment directive. If doing the
alignment would require skipping more bytes than the specified maximum, then the alignment is not done at all. You can omit the fill value (the second
argument) entirely by simply using two commas after the required alignment; this can be useful if you want the alignment to be filled with no-op instructions
when appropriate.
The way the required alignment is specified varies from system to system. For the a29k, hppa, m68k, m88k, w65, sparc, Xtensa, and Renesas / SuperH SH,
and i386 using ELF format, the first expression is the alignment request in bytes. For example .align 8 advances the location counter until it is a multiple of 8.
If the location counter is already a multiple of 8, no change is needed.
For other systems, including the i386 using a.out format, and the arm and strongarm, it is the number of low-order zero bits the location counter must have
after advancement. For example .align 3 advances the location counter until it a multiple of 8. If the location counter is already a multiple of 8, no change is
needed.
This inconsistency is due to the different behaviors of the various native assemblers for these systems which as must emulate. as also provides .balign
and .p2align directives, which have a consistent behavior across all architectures (but are specific to as).
.ascii
.ascii expects zero or more string literals (see Strings) separated by commas. It assembles each string (with no automatic trailing zero byte) into consecutive
addresses.
.asciz
.asciz is just like .ascii, but each string is followed by a zero byte. The "z" in .asciz stands for "zero".
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 119 of 173
.balign[wl]
Pad the location counter (in the current subsection) to a particular storage boundary. alignment (which must be absolute) is the alignment request in bytes. For
example .balign 8 advances the location counter until it is a multiple of 8. If the location counter is already a multiple of 8, no change is needed.
fill (also absolute) gives the fill value to be stored in the padding bytes. It (and the comma) may be omitted. If it is omitted, the padding bytes are normally
zero. However, on some systems, if the section is marked as containing code and the fill value is omitted, the space is filled with no-op instructions (I didn't
checked whether this is the case in TIGCC).
max is also absolute, and is also optional. If it is present, it is the maximum number of bytes that should be skipped by this alignment directive. If doing the
alignment would require skipping more bytes than the specified maximum, then the alignment is not done at all. You can omit the fill value (the second
argument) entirely by simply using two commas after the required alignment; this can be useful if you want the alignment to be filled with no-op instructions
when appropriate.
The .balignw and .balignl directives are variants of the .balign directive. The .balignw directive treats the fill pattern as a two byte word value.
The .balignl directives treats the fill pattern as a four byte longword value. For example, .balignw 4,0x368d will align to a multiple of 4. If it skips two bytes,
they will be filled in with the value 0x368d (the exact placement of the bytes depends upon the endianness of the processor). If it skips 1 or 3 bytes, the fill
value is undefined.
.byte
.byte expects zero or more expressions, separated by commas. Each expression is assembled into the next byte.
.comm
.comm declares a common symbol named symbol. When linking, a common symbol in one object file may be merged with a defined or common symbol of the
same name in another object file. If ld does not see a definition for the symbol - just one or more common symbols - then it will allocate length bytes of
uninitialized memory. length must be an absolute expression. If ld sees multiple common symbols with the same name, and they do not all have the same
size, it will allocate space using the largest size.
.data
.data tells as to assemble the following statements onto the end of the data subsection numbered subsection (which is an absolute expression). If subsection is
omitted, it defaults to zero.
In order to be compatible with the Sun assembler, the 680x0 assembler understands the directives .data1 and .data2 as alternatives to .data 1 and .data 2.
.def
Begin defining debugging information for a symbol name; the definition extends until the .endef directive is encountered.
.dim
This directive is generated by compilers to include auxiliary debugging information in the symbol table. It is only permitted inside .def/.endef pairs.
.double
.double expects zero or more flonums, separated by commas. It assembles floating point numbers.
.eject
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 120 of 173
.else
.else is part of the as support for conditional assembly; see .if. It marks the beginning of a section of code to be assembled if the condition for the
preceding .if was false.
.end
.end marks the end of the assembly file. as does not process anything in the file past the .end directive.
.elseif
.elseif is part of the as support for conditional assembly; see .if. It is shorthand for beginning a new .if block that would otherwise fill the entire .else
section.
.endef
This directive flags the end of a symbol definition begun with .def.
.endfunc
.endif
.endif is part of the as support for conditional assembly; it marks the end of a block of code that is only assembled conditionally. See .if.
.endm
.endr
.equ
This directive sets the value of symbol to expression. It is synonymous with .set.
.equiv
The .equiv directive is like .equ and .set, except that the assembler will signal an error if symbol is already defined. Note a symbol which has been referenced
but not actually defined is considered to be undefined.
Except for the contents of the error message, this is roughly equivalent to
.ifdef SYM
.err
.endif
.equ SYM,VAL
.err
If as assembles a .err directive, it will print an error message and, unless the '-Z' option was used, it will not generate an object file. This can be used to
signal error an conditionally compiled code.
.even
This directive is a special case of the .align directive; it aligns the output to an even byte boundary. It is 680x0-specific; introduced in order to be compatible
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 121 of 173
.exitm
.extern
.extern is accepted in the source program - for compatibility with other assemblers - but it is ignored. as treats all undefined symbols as external.
.fail
Generates an error or a warning. If the value of the expression is 500 or more, as will print a warning message. If the value is less than 500, as will print an
error message. The message will include the value of expression. This can occasionally be useful inside complex nested macros or conditional assembly.
.file
.file tells as that we are about to start a new logical file. string is the new file name. In general, the filename is recognized whether or not it is surrounded by
quotes ("); but if you wish to specify an empty file name, you must give the quotes "".
.fill
repeat, size and value are absolute expressions. This emits repeat copies of size bytes. Repeat may be zero or more. Size may be zero or more, but if it is more
than 8, then it is deemed to have the value 8, compatible with other people's assemblers. The contents of each repeat bytes is taken from an 8-byte number.
The highest order 4 bytes are zero. The lowest order 4 bytes are value rendered in the byte-order of an integer on the computer as is assembling for (big-
endian for 680x0). Each size bytes in a repetition is taken from the lowest order size bytes of this number. Again, this bizarre behavior is compatible with other
people's assemblers.
size and value are optional. If the second comma and value are absent, value is assumed zero. If the first comma and following tokens are absent, size is
assumed to be 1.
.float
This directive assembles zero or more flonums, separated by commas. It has the same effect as .single.
.func
.func emits debugging information to denote function name, and is ignored unless the file is assembled with debugging enabled. Only '--gstabs' is currently
supported. label is the entry point of the function, and if omitted, name prepended with the leading character is used (no leading character in TIGCC). All
functions are currently defined to have void return type. The function must be terminated with .endfunc.
.global
.global makes the symbol visible to ld. If you define symbol in your partial program, its value is made available to other partial programs that are linked with
it. Otherwise, symbol takes its attributes from a symbol of the same name from another file linked into the same program.
Both spellings (.globl and .global) are accepted, for compatibility with other assemblers. .xdef is also accepted as a synonym for .global.
.hword
This expects zero or more expressions, and emits a 16 bit number for each.
On this target, this directive is a synonym for both .short and .word.
.ident
This directive is used by some assemblers to place tags in object files. as simply accepts the directive for source-file compatibility with such assemblers, but
does not actually emit anything for it.
.if
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 122 of 173
.if marks the beginning of a section of code which is only considered part of the source program being assembled if the argument (which must be an absolute
expression) is non-zero. The end of the conditional section of code must be marked by .endif; optionally, you may include code for the alternative condition,
flagged by .else. If you have several conditions to check, .elseif may be used to avoid nesting blocks if/else within each subsequent .else block.
.ifdef symbol
Assembles the following section of code if the specified symbol has been defined. Note a symbol which has been referenced but not yet defined is
considered to be undefined.
.ifndef symbol
.ifnotdef symbol
Assembles the following section of code if the specified symbol has not been defined. Both spelling variants are equivalent. Note a symbol which has been
referenced but not yet defined is considered to be undefined.
.include
This directive provides a way to include supporting files at specified points in your source program. The code from file is assembled as if it followed the point of
the .include; when the end of the included file is reached, assembly of the original file continues. You can control the search paths used with the '-I'
command-line option (see Command-Line Options). Quotation marks are required around file.
.incbin
The incbin directive includes file verbatim at the current location. You can control the search paths used with the '-I' command-line option (see Command-Line
Options). Quotation marks are required around file.
The skip argument skips a number of bytes from the start of the file. The count argument indicates the maximum number of bytes to read. Note that the data
is not aligned in any way, so it is the user's responsibility to make sure that proper alignment is provided both before and after the incbin directive.
.int
Expect zero or more expressions, of any section, separated by commas. For each expression, emit a number that, at run time, is the value of that expression.
The byte order and bit size of the number depends on what kind of target the assembly is for (big endian 32-bit for MC 68000; be aware that in TIGCC, C
language int variables occupy 16 bits by default).
.irp
Evaluate a sequence of statements assigning different values to symbol. The sequence of statements starts at the .irp directive, and is terminated by an .endr
directive. For each value, symbol is set to value, and the sequence of statements is assembled. If no value is listed, the sequence of statements is assembled
once, with symbol set to the null string. To refer to symbol within the sequence of statements, use \symbol.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 123 of 173
.irp param,1,2,3
move.l %d\param,-(%sp)
.endr
is equivalent to assembling
move %d1,-(%sp)
move.l %d2,-(%sp)
move.l %d3,-(%sp)
.irpc
Evaluate a sequence of statements assigning different values to symbol. The sequence of statements starts at the .irpc directive, and is terminated by
an .endr directive. For each character in value, symbol is set to the character, and the sequence of statements is assembled. If no value is listed, the sequence
of statements is assembled once, with symbol set to the null string. To refer to symbol within the sequence of statements, use \symbol.
.irpc param,123
move.l %d\param,-(%sp)
.endr
is equivalent to assembling
move.l %d1,-(%sp)
move.l %d2,-(%sp)
move.l %d3,-(%sp)
.lcomm
Reserve length (an absolute expression) bytes for a local common denoted by symbol. The section and value of symbol are those of the new local common. The
addresses are allocated in the bss section, so that at run-time the bytes start off zeroed. Symbol is not declared global (see .global), so is normally not visible
to ld.
.lflags
as accepts this directive, for compatibility with other assemblers, but ignores it.
.line
Even though this is a directive associated with the a.out or b.out object-code formats, as still recognizes it when producing COFF output, and treats .line as
though it were the COFF .ln if it is found outside a .def/.endef pair.
Inside a .def, .line is, instead, one of the directives used by compilers to generate auxiliary symbol information for debugging.
.ln
Change the logical line number. line-number must be an absolute expression. The next line has that logical line number. Therefore any other statements on the
current line (after a statement separator character) are reported as on logical line number line-number-1.
.list
Control (in conjunction with the .nolist directive) whether or not assembly listings are generated. These two directives maintain an internal counter (which is
zero initially). .list increments the counter, and .nolist decrements it. Assembly listings are generated whenever the counter is greater than zero.
By default, listings are disabled. When you enable them (with the '-a' command line option; see Command-Line Options), the initial value of the listing counter
is one.
.long
.macro
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 124 of 173
The commands .macro and .endm allow you to define macros that generate assembly output. For example, this definition specifies a macro sum that puts a
sequence of numbers into memory:
With that (recursive) definition, SUM 0,5 is equivalent to this assembly input:
.long 0
.long 1
.long 2
.long 3
.long 4
.long 5
.macro macname
.macro macname macargs
Begin the definition of a macro called macname. If your macro definition requires arguments, specify their names after the macro name, separated by
commas or spaces. You can supply a default value for any macro argument by following the name with =deflt. For example, these are all valid .macro
statements:
.macro comm
Begin the definition of a macro called comm, which takes no arguments.
.macro plus1 p, p1
.macro plus1 p p1
Either statement begins the definition of a macro called plus1, which takes two arguments; within the macro definition, write \p or \p1 to evaluate
the arguments.
When you call a macro, you can specify the argument values either by position, or by keyword. For example, sum 9,17 is equivalent to
sum to=17, from=9.
.endm
Mark the end of a macro definition.
.exitm
Exit early from the current macro definition.
\
as maintains a counter of how many macros it has executed in this pseudo-variable; you can copy that number to your output with \@, but only within a
macro definition.
.mri
If val is non-zero, this tells as to enter MRI mode. If val is zero, this tells as to exit MRI mode. This change affects code assembled until the next .mri directive,
or until the end of the file.
.nolist
Control (in conjunction with the .list directive) whether or not assembly listings are generated. These two directives maintain an internal counter (which is
zero initially). .list increments the counter, and .nolist decrements it. Assembly listings are generated whenever the counter is greater than zero.
.octa
This directive expects zero or more bignums, separated by commas. For each bignum, it emits a 16-byte integer.
The term "octa" comes from contexts in which a "word" is two bytes; hence octa-word for 16 bytes.
.org
Advance the location counter of the current section to new-lc. new-lc is either an absolute expression or an expression with the same section as the current
subsection. That is, you can't use .org to cross sections: if new-lc has the wrong section, the .org directive is ignored. To be compatible with former
assemblers, if the section of new-lc is absolute, as issues a warning, then pretends the section of new-lc is the same as the current subsection.
.org may only increase the location counter, or leave it unchanged; you cannot use .org to move the location counter backwards.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 125 of 173
Because as tries to assemble programs in one pass, new-lc may not be undefined. If you really detest this restriction we eagerly await a chance to share your
improved assembler.
Beware that the origin is relative to the start of the section, not to the start of the subsection. This is compatible with other people's assemblers.
When the location counter (of the current subsection) is advanced, the intervening bytes are filled with fill which should be an absolute expression. If the
comma and fill are omitted, fill defaults to zero.
.p2align[wl]
Pad the location counter (in the current subsection) to a particular storage boundary. alignment (which must be absolute) is the number of low-order zero bits
the location counter must have after advancement. For example .p2align 3 advances the location counter until it a multiple of 8. If the location counter is
already a multiple of 8, no change is needed.
fill (also absolute) gives the fill value to be stored in the padding bytes. It (and the comma) may be omitted. If it is omitted, the padding bytes are normally
zero. However, on some systems, if the section is marked as containing code and the fill value is omitted, the space is filled with no-op instructions (I didn't
checked whether this is the case in TIGCC).
max is also absolute, and is also optional. If it is present, it is the maximum number of bytes that should be skipped by this alignment directive. If doing the
alignment would require skipping more bytes than the specified maximum, then the alignment is not done at all. You can omit the fill value (the second
argument) entirely by simply using two commas after the required alignment; this can be useful if you want the alignment to be filled with no-op instructions
when appropriate.
The .p2alignw and .p2alignl directives are variants of the .p2align directive. The .p2alignw directive treats the fill pattern as a two byte word value.
The .p2alignl directives treats the fill pattern as a four byte longword value. For example, .p2alignw 2,0x368d will align to a multiple of 4. If it skips two
bytes, they will be filled in with the value 0x368d (the exact placement of the bytes depends upon the endianness of the processor). If it skips 1 or 3 bytes, the
fill value is undefined.
as will print string on the standard output during assembly. You must put string in double quotes.
.psize
Use this directive to declare the number of lines - and, optionally, the number of columns - to use for each page, when generating listings.
If you do not use .psize, listings use a default line-count of 60. You may omit the comma and columns specification; the default width is 200 columns.
as generates formfeeds whenever the specified number of lines is exceeded (or whenever you explicitly request one, using .eject).
If you specify lines as 0, no formfeeds are generated save those explicitly specified with .eject.
.purgem
Undefine the macro macname, so that later uses of the string will not be expanded.
.quad
.quad expects zero or more bignums, separated by commas. For each bignum, it emits an 8-byte integer. If the bignum won't fit in 8 bytes, it prints a warning
message; and just takes the lowest order 8 bytes of the bignum.
The term "quad" comes from contexts in which a "word" is two bytes; hence quad-word for 8 bytes.
.rept
Repeat the sequence of lines between the .rept directive and the next .endr directive count times.
.rept 3
.long 0
.endr
is equivalent to assembling
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 126 of 173
.long 0
.long 0
.long 0
.sbttl
Use subheading as the title (third line, immediately after the title line) when generating assembly listings.
This directive affects subsequent pages, as well as the current page if it appears within ten lines of the top of a page.
.scl
Set the storage-class value for a symbol. This directive may only be used inside a .def/.endef pair. Storage class may flag whether a symbol is static or
external, or it may record further symbolic debugging information.
.section
Use the .section directive to assemble the following code into a section named name.
If the optional argument is quoted, it is taken as flags to use for the section. Each flag is a single character. The following flags are recognized:
b
bss section (uninitialized data)
n
section is not loaded
w
writable section
d
data section
r
read-only section
x
executable section
m
mergeable section (TIGCC extension, symbols in the section are considered mergeable constants)
u
unaligned section (TIGCC extension, the contents of the section need not be aligned)
s
shared section (meaningful for PE targets, useless for TIGCC)
a
ignored (for compatibility with the ELF version)
If no flags are specified, the default flags depend upon the section name. If the section name is not recognized, the default will be for the section to be loaded
and writable. Note the n and w flags remove attributes from the section, rather than adding them, so if they are used on their own it will be as if no flags had
been specified at all.
If the optional argument to the .section directive is not quoted, it is taken as a subsegment number (see Sub-Sections).
.set
Set the value of symbol to expression. This changes symbol's value and type to conform to expression. If symbol was flagged as external, it remains flagged
(see Symbol Attributes).
If you .set a global symbol, the value stored in the object file is the last value stored into it.
.short
.single
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 127 of 173
This directive assembles zero or more flonums, separated by commas. It has the same effect as .float.
.size
This directive, permitted only within .def/.endef pairs, is used to set the size associated with a symbol.
.sleb128
sleb128 stands for "signed little endian base 128." This is a compact, variable length representation of numbers used by the DWARF symbolic debugging
format.
.skip
.space
This directive emits size bytes, each of value fill. Both size and fill are absolute expressions. If the comma and fill are omitted, fill is assumed to be zero.
.stabd
There are three directives that begin .stab. All emit symbols (see Symbols), for use by symbolic debuggers (not integrated into TIGCC yet, but it will use COFF
debugging anyway). The symbols are not entered in the as hash table: they cannot be referenced elsewhere in the source file. Up to five fields are required:
string
This is the symbol's name. It may contain any character except \000, so is more general than ordinary symbol names. Some debuggers used to code
arbitrarily complex structures into symbol names using this field.
type
An absolute expression. The symbol's type is set to the low 8 bits of this expression. Any bit pattern is permitted, but ld and debuggers choke on silly bit
patterns.
other
An absolute expression. The symbol's "other" attribute is set to the low 8 bits of this expression.
desc
An absolute expression. The symbol's descriptor is set to the low 16 bits of this expression.
value
An absolute expression which becomes the symbol's value.
If a warning is detected while reading a .stabd, .stabn, or .stabs statement, the symbol has probably already been created; you get a half-formed symbol in
your object file. This is compatible with earlier assemblers!
If .stabd is used, the "name" of the symbol generated is not even an empty string. It is a null pointer, for compatibility. Older assemblers used a null pointer
so they didn't waste space in object files with empty strings.
The symbol's value is set to the location counter, relocatably. When your program is linked, the value of this symbol is the address of the location counter when
the .stabd was assembled. If .stabn is used, the name of the symbol is set to the empty string "". If .stabs is used, all five fields are required.
.stabn
See .stabd.
.stabs
See .stabd.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 128 of 173
.string
Copy the characters in str to the object file. You may specify more than one string to copy, separated by commas. The assembler marks the end of each string
with a 0 byte. You can use any of the escape sequences described in Strings.
.struct
Switch to the absolute section, and set the section offset to expression, which must be an absolute expression. You might use this as follows:
.struct 0
field1:
.struct field1 + 4
field2:
.struct field2 + 4
field3:
This would define the symbol field1 to have the value 0, the symbol field2 to have the value 4, and the symbol field3 to have the value 8. Assembly would
be left in the absolute section, and you would need to use a .section directive of some sort to change to some other section before further assembly.
.tag
This directive is generated by compilers to include auxiliary debugging information in the symbol table. It is only permitted inside .def/.endef pairs. Tags are
used to link structure definitions in the symbol table with instances of those structures.
.text
Tells as to assemble the following statements onto the end of the text subsection numbered subsection, which is an absolute expression. If subsection is
omitted, subsection number zero is used.
.title
Use heading as the title (second line, immediately after the source file name and pagenumber) when generating assembly listings.
This directive affects subsequent pages, as well as the current page if it appears within ten lines of the top of a page.
.type
This directive, permitted only within .def/.endef pairs, records the integer int as the type attribute of a symbol table entry.
.uleb128
uleb128 stands for "unsigned little endian base 128." This is a compact, variable length representation of numbers used by the DWARF symbolic debugging
format.
.val
This directive, permitted only within .def/.endef pairs, records the address addr as the value attribute of a symbol table entry.
.vtable_entry
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 129 of 173
This directive finds or creates a symbol table and creates a VTABLE_ENTRY relocation for it with an addend of offset.
.word
This directive expects zero or more expressions, of any section, separated by commas. For each expression, as emits a 16-bit number for this target.
Acknowledgements
If you have contributed to as and your name isn't listed here, it is not meant as a slight. We just don't know about it. Send mail to the maintainer, and we'll
correct the situation. Currently the maintainer is Ken Raeburn (email address [email protected]). (Note: Since this is a modified version of the manual,
please check the original version as well before sending a mail.)
Dean Elsner wrote the original GNU assembler for the VAX. Any more details?
Jay Fenlason maintained GAS for a while, adding support for GDB-specific debug information and the 68k series machines, most of the preprocessing pass, and
extensive changes in messages.c, input-file.c, write.c.
K. Richard Pixley maintained GAS for a while, adding various enhancements and many bug fixes, including merging support for several processors, breaking
GAS up to handle multiple object file format back ends (including heavy rewrite, testing, an integration of the coff and b.out back ends), adding configuration
including heavy testing and verification of cross assemblers and file splits and renaming, converted GAS to strictly ANSI C including full prototypes, added
support for m680[34]0 and cpu32, did considerable work on i960 including a COFF port (including considerable amounts of reverse engineering), a SPARC
opcode file rewrite, DECstation, rs6000, and hp300hpux host ports, updated "know" assertions and made them work, much other reorganization, cleanup, and
lint.
Ken Raeburn wrote the high-level BFD interface code to replace most of the code in format-specific I/O modules.
The original VMS support was contributed by David L. Kashtan. Eric Youngdale has done much work with it since.
The Motorola 88k machine description was contributed by Devon Bowen of Buffalo University and Torbjorn Granlund of the Swedish Institute of Computer
Science.
Keith Knowles at the Open Software Foundation wrote the original MIPS back end (tc-mips.c, tc-mips.h), and contributed Rose format support (which hasn't
been merged in yet). Ralph Campbell worked with the MIPS code to support a.out format.
Support for the Zilog Z8k and Renesas H8/300 and H8/500 processors (tc-z8k, tc-h8300, tc-h8500), and IEEE 695 object file format (obj-ieee), was written by
Steve Chamberlain of Cygnus Support. Steve also modified the COFF back end to use BFD for some low-level operations, for use with the H8/300 and AMD 29k
targets.
John Gilmore built the AMD 29000 support, added .include support, and simplified the configuration of which versions accept which directives. He updated the
68k machine description so that Motorola's opcodes always produced fixed-size instructions (e.g., jsr), while synthetic instructions remained shrinkable (jbsr).
John fixed many bugs, including true tested cross-compilation support, and one bug in relaxation that took a week and required the proverbial one-bit fix.
Ian Lance Taylor of Cygnus Support merged the Motorola and MIT syntax for the 68k, completed support for some COFF targets (68k, i386 SVR3, and SCO
Unix), added support for MIPS ECOFF and ELF targets, wrote the initial RS/6000 and PowerPC assembler, and made a few other minor patches.
Jeff Law wrote GAS and BFD support for the native HPPA object format (SOM) along with a fairly extensive HPPA testsuite (for both SOM and ELF object
formats). This work was supported by both the Center for Software Science at the University of Utah and Cygnus Support.
Support for ELF format files has been worked on by Mark Eichin of Cygnus Support (original, incomplete implementation for SPARC), Pete Hoogenboom and Jeff
Law at the University of Utah (HPPA mainly), Michael Meissner of the Open Software Foundation (i386 mainly), and Ken Raeburn of Cygnus Support (sparc, and
some initial 64-bit support).
Linas Vepstas added GAS support for the ESA/390 "IBM 370" architecture.
Richard Henderson rewrote the Alpha assembler. Klaus Kaempf wrote GAS and BFD support for openVMS/Alpha.
Timothy Wall, Michael Hayes, and Greg Smart contributed to the various tic* flavors.
David Heine, Sterling Augustine, Bob Wilson and John Ruttenberg from Tensilica, Inc. added support for Xtensa processors.
Several engineers at Cygnus Support have also provided many small bug fixes and configuration enhancements.
Many others have contributed large or small bugfixes and enhancements. If you have contributed significant work and are not mentioned on this list, and want
to be, let us know. Some of the history has been lost; we are not intentionally leaving anyone out.
History
Copyright © 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Copyright © 2000, 2001, 2002, 2003 Zeljko Juric, Sebastian Reichelt, Kevin Kofler
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 130 of 173
In addition to the GNU Assembler, the TIGCC package also includes the A68k assembler by Charlie Gibbs (slightly modified Amiga version). Although TIGCC
also includes the GNU assembler used by GCC, A68k is included here because almost all assembly programs for the TI-89 and TI-92+ are created just with this
assembler, so including it in the package allows compiling existing ASM programs as well, and because, while it is inferior to the GNU assembler in some
aspects, it also has its advantages, mainly easier syntax, but also support for binary include files for example. As this part of the TIGCC package was developed
completely independently of the rest of the TIGCC project (and long before the TIGCC project was even started), it is somewhat inconsistent with the rest of the
project, but some effort has been made to integrate it into TIGCC. For example, you can now call a function from a static library using a simple bsr or jsr
instruction.
This assembler comes with its own set of header files. All of them are included mainly for compatibility reasons (note that some of them are deprecated,
obsolete, inconsistent or even obscure), so they will not be described here. Information about them may be found in various ASM tutorials for TI-89 and TI-92+
(also deprecated, but note that nearly 95% of all ASM programs for TI-89 and TI-92+ are written using a now deprecated way, because a lot of information
about the system was not available at the time when these programs were created). We recommend using only OS.h, which contains a list of equates for
ROM_CALLs (but the ROM_CALL macros are not very optimized and should thus be avoided), and functions from TIGCCLIB, which need no header file at all (for
example, bsr GrayOn is enough to call the GrayOn function). What will be presented here is the original A68k documentation, written by Charlie Gibbs himself.
We have however annotated it in some places to reflect the changes made in recent versions, and we have added 2 chapters: the list of supported assembler
directives, which was missing, and the history, which was kept in a separate file.
Note: This program is Freely Distributable, as opposed to Public Domain. Permission is given to freely distribute this program provided no fee is charged, and
this documentation file is included with the program.
This assembler is based on Brian R. Anderson's 68000 cross- assembler published in Dr. Dobb's Journal, April through June 1986. I have converted it to
produce AmigaDOS-format object modules, and have made many enhancements, such as macros and INCLUDE files.
My first step was to convert the original Modula-2 code into C. I did this for two reasons. First, I had access to a C compiler, but not a Modula-2 compiler.
Second, I like C better anyway.
The executable code generator code (GetObjectCode and MergeModes) is essentially the same as in the original article, aside from its translation into C. I have
almost completely rewritten the remainder of the code, however, in order to remove restrictions, add enhancements, and adapt it to the AmigaDOS
environment. Since the only reference book available to me was the AmigaDOS Developer's Manual (Bantam, February 1986), this document describes the
assembler in terms of that book.
Restrictions
The verification file '-v' option is not supported. Diagnostic messages always appear on the console. They also appear in the listing file, however (see
extensions below). You can produce an error file by redirecting console output to a file - the line number counter and final summary are displayed on
stderr so you can still see what's happening.
(TIGCC) WARNING: The new -v switch introduced in v.2.71.F3c is NOT the same as this one!
The file names in the INCLUDE directory list '-i' must be separated by commas. The list may not be enclosed in quotes.
Labels assigned by EQUR and REG directives are case-sensitive.
Strange things will happen if your source code (including INCLUDE files and macro expansions) exceeds 32,766 lines. Tough darts. Break up your source
file. Can you actually read that monster?
(TIGCC) The maximum has been increased from 32,766 to 2,147,483,646 for 32-bit operating systems starting from version 2.71.F3s.
Directives OFFSET, NOPAGE, LLEN, PLEN, NOOBJ, FAIL, FORMAT, NOFORMAT and MASK2 are not supported, and will be flagged as invalid op-codes. I feel that
NOPAGE, LLEN, and PLEN should not be defined within a source module. It doesn't make sense to me to have to change your program just because you
want to print your listings on different paper. The command-line switch '-p' (see below) can be used as a replacement for PLEN; setting it to a high value
(like 32767) is a good substitute for NOPAGE. The effect of LLEN can be obtained by running the listing file through an appropriate filter.
Extensions
Labels can be any length that will fit onto one source line (currently 127 characters maximum). Since labels are stored on the heap, the number of labels
that can be processed is limited only by available memory.
The maximum has been increased from 127 to 256 (for Win32, starting from 2.71.F3a, for GNU/Linux, starting from 2.71.F3c, for all other
(TIGCC)
platforms, starting from 2.71.F3s).
The first character of a label can be '@' if the next character is not numeric (this avoids confusion with octal constants). This provides compatibility with
the Lattice C compiler.
Since section data and user macro definitions are stored in the symbol table (see above), they too are limited only by available memory (actually, there is
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 131 of 173
a hard-coded limit of 32,767 sections, but I doubt anyone will run into that one).
The only values a label cannot take are the register names - A68k can distinguish between the same name used as a label, instruction name or directive,
macro name, or section name.
Section and user macro names appear in the symbol table dump, and will also be cross-referenced. Their names can be the same as any label (see
above); they will be listed separately.
INCLUDEs and macro calls can be nested indefinitely, limited only by available memory. The message "Secondary heap overflow - assembly terminated"
will be displayed if memory is exhausted. You can increase the size of this heap using the '-w' switch (see below). Recursive macros are supported;
recursive INCLUDEs will, of course, result in a loop that will be broken only when the heap overflows.
The EVEN directive forces alignment on a word (2-byte) boundary. It does the same thing as CNOP 0,2 (this one is left over from the original code).
Backward references to labels within the current CODE section will be converted to PC-relative addressing with displacement if this mode is legal for the
instruction. This feature is disabled by the '-n' switch.
If a MOVEM instruction only specifies one register, it is converted to the corresponding MOVE instruction. Instructions such as MOVEM D0-D0,label will not
be converted, however. This feature is disabled by the '-n' switch.
(TIGCC) Starting from v.2.71.F3c, this feature can now also be disabled by using the '-rm' switch.
ADD, SUB, and MOVE instructions will be converted to ADDQ, SUBQ, and MOVEQ respectively if possible. Instructions coded explicitly (e.g. ADDA or ADDI) will
not be converted. This feature is disabled by the '-n' switch.
ADD, CMP, SUB, and MOVE to an address register are converted to ADDA, CMPA, SUBA, and MOVEA respectively, unless (for ADD, SUB, or MOVE) they have
already been converted to quick form.
ADD, AND, CMP, EOR, OR, and SUB of an immediate value are converted to ADDI, ANDI, CMPI, EORI, ORI, and SUBI respectively (unless the address register
or quick conversion above has already been done).
Starting from v.2.71.F3c, ADDA and SUBA (or ADD and SUB to an address register) will now be converted to LEA if possible. This feature can be
(TIGCC)
disabled using the '-n' switch (disables all optimizations) or the '-ra' switch (disables just this single optimization).
Starting from v.2.71.F3c, LEA n(an),an will now be converted to ADDQ or SUBQ if possible. This feature can be disabled using the '-n' switch
(TIGCC)
(disables all optimizations) or the '-rl' switch (disables just this single optimization).
If both operands of a CMP instruction are postincrement mode, the instruction is converted to CMPM.
Operands of the form '0(An)' will be treated as '(An)' except for the MOVEP instruction, which always requires a displacement. This feature is disabled
by the '-n' switch.
The SECTION directive allows a third parameter. This can be specified as either CHIP or FAST (upper or lower case). If this parameter is present, the hunk
will be written with the MEMF_CHIP or MEMF_FAST bit set. This allows you to produce "pre-ATOMized" object modules.
The synonyms DATA and BSS are accepted for SECTION directives starting data or BSS hunks. The CHIP and FAST options (see above) can also be used,
e.g. BSS name,CHIP.
The following synonyms have been implemented for compatibility with the Aztec assembler:
MOVEQ "'",D0
DC.B "This is Charlie's assembler."
Note that you can still define an apostrophe within a string delimited by apostrophes if you double it, e.g.
MOVEQ '''',D0
DC.B 'This is Charlie''s assembler.'
If any errors are found in the assembly, the object code file will be scratched, unless you include the '-k' (keep) flag on the command line.
The symbols .A68K, .a68k, .a68K, and .A68k are automatically defined as SET symbols having absolute values of 1. This enables a source program to
determine whether it is being assembled by this assembler, and is effectively insensitive as to whether or not it is checked in upper case.
A zeroth positional macro parameter '\0' is supported. It is replaced by the length of the macro call (B, W, or L, defaulting to W). For instance, given the
macro:
moov MACRO
move.\0 \1,\2
ENDM
moov.l d0,d1
would be expanded as
move.l d0,d1
If an INCLUDE file doesn't generate any code and no listing file is required (including suppression of the listing using NOLIST), it won't be read again in
pass 2. The statement numbers will be bumped to keep in proper alignment. This can really speed up assemblies that INCLUDE lots of EQUates.
The ORG directive is supported. It works like RORG, except that it takes the actual address to be jumped to, rather than an offset from the start of the
current section. The given address must be in the current section. As far as A68k is concerned, the only real difference between ORG and RORG is that the
ORG value must be relocatable, while the RORG value must be absolute.
Branch (Bcc, including BRA and BSR) instructions will be converted to short form if possible. Shortening a branch may bring other branches within range of
shortening - this can set up a ripple effect, and A68k may not catch all branches that could theoretically be optimized. Any branches which A68k misses
(there shouldn't be too many under normal circumstances) can be displayed by specifying the '-f' switch (see below). Branch optimization is disabled by
the '-n' switch.
The INCBIN directive allows the contents of any file to be included in A68k's object code output. Its format is the same as the INCLUDE directive, but the
file can contain any data at all, printable or not. Rather than being processed as source code by the assembler, the entire contents of the file is copied
directly to the current position in the object code output file with no reformatting whatsoever. The effect is the same as if DC statements whose constants
represent the file's contents were inserted in place of the INCBIN directive.
The opcode TTL is accepted as a synonym for TITLE.
A command-line option '-g' causes A68k to treat any undefined symbol as XREF.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 132 of 173
The register list in a MOVEM instruction can be an immediate operand which specifies the actual mask bits.
BLO = BCS
BHS = BCC
DBLO = DBCS
DBHS = DBCC
(TIGCC)
ROLX = ROXL
RORX = ROXR
SLO = SCS
SHS = SCC
Note: This section has been written entirely by the TIGCC Team. Part of the information comes from direct.txt by Mathieu Lacage, but the whole text is
completely rewritten and contains more details. Also, some of the directives listed here are not documented in direct.txt.
arithmetic operators Arithmetic operators can be used exactly like their C counterparts, except that spaces are not allowed in an expression. But
((1+2)>>3)/4 is a perfectly legitimate A68k expression. Of course, you can not use anything other than + or - on labels and
you cannot use arithmetic on registers at all - you will have to use the corresponding assembly instructions.
INCLUDE "filename.h" Includes the file given as a parameter at the current source position. The file is read in as assembly source code, as if it was
part of the current assembly source.
INCBIN "filename.bin" Includes the binary content of the file given as a parameter as-is at the current location in the object file output. The file will
NOT be assembled, but included as binary data.
EVEN Forces alignment on an even address. The next instruction will be guaranteed to be placed at an even address. This is
especially important for dc.w or dc.l directives, since accessing a word or longword at an odd address causes an address
error.
CNOP displacement,alignment Forces alignment on an address which is the sum of displacement, which has to be even, and a multiple of alignment, which
has to be a power of 2.
XDEF label Exports the label given as an argument to other object files or to the linker. This also allows linker directives like
xdef _nostub.
XREF label Imports the label given as an argument. This allows to access variables from other object files even if the '-g' switch is not
specified. Since TIGCC specifies '-g' by default, there is no real need for this directive.
PUBLIC label Imports or exports the label given as an argument, depending on whether it is part of the current source file or not. We
recommend using XDEF or XREF instead when possible, since they clearly specify what is meant. But PUBLIC is useful when
used in a common header file for multiple source files.
SECTION "sectname" Sets the section the following code will be written to. This is especially useful to make A68k use the same section as GCC:
.data, in order to make sure the linking order of GCC files first is respected. (Note: You can deliberately NOT specify
SECTION ".data" if you want the A68k file to be the main file.)
BSS Specifies the section the following code will be written to as a "BSS section", a section which will not be initialized at runtime,
so it can contain only storage place which does not need to be initialized. Also, BSS sections are not allowed in _nostub
mode.
CSEG Creates a section called "CODE" where the code will be written to. This directive is not really useful in TIGCC, since both code
and data are written to the .data section by GCC and GNU as.
DSEG Creates a section called "DATA" where the code will be written to. Do not use this directive in TIGCC. Instead, specify
SECTION .data, which is the section name used by GCC and GNU as for data sections.
END Marks the end of the source file. This directive is now optional since v.2.71.F3c.
DC.{B|W|L} data1,data2,... (Define Constant(s)) Will insert all the arguments as immediate data into the object file. For example, DC.L $12345678 will
insert the bytes 0x12, 0x34, 0x56 and 0x78 into the resulting object file. DC.B 'Hello, World!',0 will insert the null-
terminated string "Hello, World!" into the resulting object file.
DS.{B|W|L} n (Define Storage) Will insert n bytes, words or longwords (depending on the size specified) of zeros (0, NOT '0') into the
resulting object file.
DCB.{B|W|L} n,data (Define Constant Block) Will act as n times the DC.B data instruction. It will insert the immediated data specified by data n
times into the resulting object file.
macroName MACRO This declares a macro so that macroName can be used as if it was an instruction, with the difference that unlike opcodes,
instructions macro names are case-sensitive. You can also pass arguments to a macro. Those are referenced by a macro as \n, where n
ENDM
is the number of the argument, starting from 1. \0 indicates the instruction size. \@ indicates the number of the current
macro, which is useful to create unique labels of the form \@label or \\@localLbl. Therefore:
PUSH MACRO
MOVE.\0 \1,-(a7)
ENDM
(defined in "OS.h") allows you to use: PUSH.L #1 when in fact you mean: MOVE.L #1,-(a7).
<expression> Makes sure expression will be treated as a single macro parameter, even if it contains separators like commas, semicolons or
whitespace.
constant EQU value Defines a symbolic constant. Wherever constant is encountered in the code, it will be replaced by value. Note that value can
OR: constant = value also be an expression, not only a single number.
regAlias EQUR register Defines an alias for a register. For example, if you are using a5 to hold the address of the jump table in your whole program,
you can write jumpTbl EQUR a5, and then use jumpTbl wherever you would use a5.
regListAlias EQUR regList Defines an alias for a list of registers, for use in the MOVEM instruction. The syntax of regList is the same as in the MOVEM
instruction. For example, if you are frequently using MOVEM.L d0-d7/a0-a6,-(a7) and MOVEM.L (a7)+,d0-d7/a0-a6, you
might define: all REG d0-d7/a0-a6, and then use all wherever you would use d0-d7/a0-a6.
variable SET value Defines a symbolic variable. Wherever variable is encountered in the code, it will be replaced by value. But contrary to an EQU
constant, a SET variable can be modified. It can therefore be used as a counter for example, as in: counter SET counter+1.
IFEQ value
The instructions in the block will be parsed and assembled if and only if value equals 0. You can also write ENDIF as a
instructions
ENDC synonym for ENDC.
IFNE value
instructions
The instructions in the block will be parsed and assembled if and only if value does not equal 0. You can also write ENDIF as a
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 133 of 173
Version 2.4 implements a rudimentary small code/data model. It consists of converting any data reference to one of the following three addressing modes:
address register indirect with displacement using a specified address register, defaulting to A4 (for references to the DATA or BSS section);
program counter indirect with displacement (for references to the CODE section);
absolute word (for absolute and 16-bit relocatable values).
These conversions do not take place unless a NEAR directive is encountered. The NEAR directive can take one operand, which must be either an address register
or a symbol which has been equated (using EQUR) to an address register. Register A7 (SP) may not be used. If no register is given, A4 is assumed.
Conversion is done for all operands until a FAR directive is encountered. NEAR and FAR directives can occur any number of times, enabling conversion to be
turned on and off at will.
Backward references which cannot be converted (e.g. external labels declared as XREF) will remain as absolute long addressing. All forward references are
assumed to be convertible, since during pass 1 A68k has no way of telling whether conversion is possible. If conversion turns out to be impossible, invalid
object code will be generated - an error message ("Invalid forward reference") will indicate when this occurs.
Although the small code/data model can greatly reduce the size of assembled programs, several restrictions apply:
Small code and small data models are active simultaneously. You can't have one without the other, since during pass 1 A68k doesn't know whether
forward references are to CODE or to DATA/BSS.
Programs can consist of a maximum of two sections, one CODE, the other DATA or BSS. If you try to define a third section, the message "Too many
SECTIONs" will be displayed. The NEAR directive is active only within the CODE section.
While the NEAR directive is active, external labels (XREF) must be declared before they are used, CODE section references must be with 32K of the current
position (i.e. expressible as PC-relative), and DATA/BSS section references must be in the first 64K of the DATA/BSS section (i.e. expressible as address
register indirect with displacement). Any instructions which do not satisfy these requirements cannot be detected in pass 1, so A68k has no choice but to
display an error message in pass 2 ("Invalid forward reference") which in this case indicates that invalid code has been generated. To properly assemble
such instructions, you can temporarily disable conversion with a FAR directive, then resume afterwards with another NEAR directive.
Conversion cannot be done for references between modules. All external references must be left as absolute long.
A68k assumes that the base register (normally A4) points to the start of the DATA/BSS section plus 32768 bytes (this assumed offset can be changed by
the '-m' command-line parameter). The register must be preloaded with this value before executing any code converted by the NEAR directive. One way
to do this is to code the instruction that loads the register prior to the NEAR directive. Another way is to use a MOVE.L with immediate mode, which is
never converted. Here are examples of the two methods:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 134 of 173
BSS BSS
data: data:
<data areas> <data areas>
END END
I'll be the first to admit that this is a very crude and ugly implementation. I hope to improve it in future versions.
Files
The source code file - this file contains the program to be assembled. This file is an ASCII text file whose last line must be an END statement.
This END statement is no longer necessary starting from v.2.71.F3c.
(TIGCC)
Moreover, the assembler will no longer accept an END statement in include files or macros, since it did never expect that and caused bugs.
The object code file - this file is created by A68k, replacing any previous version which may exist. If any errors are encountered during the assembly, this
file will be scratched, unless the '-k' (keep) switch is specified (see below). Although this file is normally written in AmigaDOS format, the '-s' switch (see
below) will cause it to be written in Motorola S-record format instead.
The listing file - this file is optionally created by A68k and contains a listing complete with page headings (including form feeds), generated object code,
and error messages if any. It is suitable for feeding to a printer.
An equate file - this file is optionally created by A68k and consists of a leading comment line followed by EQU statements, one for each symbol
encountered by A68k whose value is absolute. This file is only created if the '-e' command-line switch is specified (see below).
A header file - if requested, this file is read by A68k immediately prior to the source code file. It treated exactly as if it were requested by an INCLUDE
statement at the front of the source file, but is selected only if the '-h' command-line switch is specified (see below).
Include files are selected by INCLUDE directives within the source file, and are inserted in the source code in place of the INCLUDE directive itself. A68k first
searches the current directory for INCLUDE files; the '-i' command-line switch (see below) specifies additional directories which can be searched.
File Names
The names of the above files can be explicitly specified. However, A68k will generate default file names in the following cases:
If the '-o' switch is omitted, a default name will be assigned to the object code file.
If the '-e' switch is specified with no file name, a default name will be assigned to the equate file.
If the '-l' or '-x' switch is specified with no file name, a default name will be assigned to the listing file.
A default name is generated by deriving a stem name from the source code file name, and appending '.o' for an object code file name ('.s' if the '-s' switch
is specified to produce Motorola S-records), '.equ' for an equate file name, or '.lst' for a listing file name. The stem name consists of all characters of the
source file name up to the last period (or the entire source file name if it contains no period). Here are some examples of default names:
These options can be given in any order. Any parameter which is not a switch (denoted by a leading hyphen) is assumed to be a file name; up to three file
names (assumed to be source, object, and listing file names respectively) can be given. A source file name is always required. If a switch is being given a value,
that value must immediately follow the switch letter with no intervening spaces. For instance, to specify a page depth of 40 lines, the specification '-p40'
should be used; '-p 40' will be rejected.
-a
Causes all relocs to be emitted, even PC-relative relocs within a section. It also emits address differences in a special TIGCC-specific format. This will
allow more aggressive linker-side optimization.
-d
Causes symbol table entries (hunk_symbol) to be written to the object module for the use of symbolic debuggers. If the switch is followed by a string of
characters, only those symbols beginning with that prefix string will be written. This can be used to suppress internal symbols generated by compilers. If
the first character is an exclamation mark ('!'), only symbols which do not begin with the following characters are written out. Here are some examples:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 135 of 173
-e
Causes an equate file (see above) to be produced. A file name can be specified; otherwise a default name will be used.
-f
Causes any branches (Bcc, BRA, BSR) that could be converted to short form to be flagged. A68k will convert as many branches as possible to short form
(unless the '-n' switch is is specified), but certain combinations of instructions may set up a ripple effect where shortening one branch brings another one
into range. This switch will cause A68k to flag any branches that it may have missed; during pass 2 it is possible to tell this, although during pass 1 it
might not be. If the '-n' switch (see below) is specified along with this switch (suppressing all optimization), no branches will be shortened, but all
branches which could be shortened will be flagged.
-g
Causes any undefined symbols to be treated as if they were externally defined (XREF), rather than being flagged as errors.
-h
Causes a header file to be read prior to the source code file. A file name must be given. The action is the same as if the first statement of the source file
were an INCLUDE statement naming the header file. To find the header file, the same directories will be searched as for INCLUDE files (see the '-i' switch
below).
-i
Specifies directories to be searched for INCLUDE files in addition to the current directory. Several names, separated by commas, may be specified. No
embedded blanks are allowed. For example, the specification
-imylib,df1:another.lib
will cause INCLUDE files to be searched for first in the current directory, then in "mylib", then in "df1:another.lib".
-k
Causes the object file to be kept even if any errors were found. Otherwise, it will be scratched if any errors occur.
-l
Causes a listing file to be produced. If you want the listing file to include a symbol table dump and cross-reference, use the '-x' switch instead (see
below).
-m
Changes the assumed offset from the start of the DATA/BSS section to the base register used when the small code/data option is activated by the NEAR
directive. If this parameter is not specified, the offset defaults to 32768.
-n
Causes all object code optimization (see above) to be disabled.
-o
Allows the default name for the object code file (see above) to be overridden.
-p
Causes the page depth to be set to the specified value. This takes the place of the PLEN directive in the Metacomco assembler. Page depth defaults to 60
lines ('-p60').
-q
Changes the interval at which A68k displays the line number it has reached in its progress through the assembly. The default is to display every 100 lines
('-q100'). Specifying larger values reduces console I/O, making assemblies run slightly faster.
If you specify a negative number (e.g. '-q-10'), line numbers will be displayed at an interval equal to the absolute value of the specified number, but will
be given as positions within the current module (source, macro, or INCLUDE) rather than as a total statement count - the module name will also be
displayed.
A special case is the value zero ('-q0' or just '-q') - this will cause all console output, except for error messages, to be suppressed.
(TIGCC) -r
Allows to disable specific optimizations:
-rm Disable the MOVEM -> MOVE optimization
-ra Disable the ADD(A)/SUB(A) -> LEA optimization
-rl Disable the LEA -> ADDQ/SUBQ optimization
You might use more than one -r switch (as in "-rm -ra") or combine them into a single switch (as in "-rma").
-s
Causes the object file to be written in Motorola S-record format, rather than AmigaDOS format. The default name for an S-record file ends with '.s'
rather than '.o; this can still be overridden with the '-o' switch, though.
-t
Allows tabs in the source file to be passed through to the listing file, rather than being expanded. In addition, tabs will be generated in the listing file to
skip from the object code to the source statement, etc. This can greatly reduce the size of the listing file, as well as making it quicker to produce. Do not
use this option if you will be displaying or listing the list file on a device which does not assume a tab stop at every 8th position.
(TIGCC) -u
Disables automatic alignment of DC.W, DC.L, DCB.W, DCB.L, DS.W, DS.L and code.
(TIGCC) -v
Allows to set a variable in the command line (like -d with GCC). The variable will be a SET, not EQU variable. Syntax: "-v<name>[,<value>]" (without
spaces, and without the quotes). Note that <value> can only be a NUMBER at the moment. (We might support symbols as values in a future version.)
The default value of <value> is 1.
-w
Specifies the sizes of fixed memory areas that A68k allocates for its own use. You should normally never have to specify this switch, but it may be useful
for tuning.
The first parameter gives the number of entries that the hash table (used for searching the symbol table) will contain. The default value of 2047 should be
enough for all but the very largest programs. The assembly will not fail if this value is too small, but may slow down if too many long hash chains must be
searched. The hashing statistics displayed by the '-y' switch (see below) can be used to tune this parameter. I've heard that you should really specify a
prime number for this parameter, but I haven't gone into hashing theory enough to know whether it's actually necessary.
The second parameter of the '-w' switch specifies the size (in bytes) of the secondary heap, which is used to store nested macro and INCLUDE file
information (see below). It defaults to 1024, which should be enough unless you use very deeply nested macros and/or INCLUDE files with long path
names.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 136 of 173
(TIGCC) The default sizes are 4095,2048 in the Win32 (since v.2.71.F3a) and GNU/Linux (since v.2.71.F3c) versions.
If you're really tight for memory, and are assembling small modules, you can use this switch to shrink these areas below their default sizes. At the end of
an assembly, a message will be displayed giving the sizes actually used, in the form of the '-w' command you would have to enter to allocate that much
space. This is primarily useful to see how much secondary heap space was used.
Note: All other memory used by A68k (e.g. the actual symbol table) is allocated as required (currently in 8K chunks).
-x
Works the same as '-l' (see above), except that a symbol table dump, including cross-reference information, will be added to the end of the listing file.
-y
Causes hashing statistics to be displayed at the end of the assembly. First the number of symbols in the table is given, followed by a summary of hash
chains by length. Chains with length zero denote unused hash table entries. Ideally (i.e. if there were no collisions) there should be as many chains with
length 1 as there are symbols, and there should be no chains of length 2 or greater. I added this option to help me tune my hashing algorithm, but you
can also use it to see whether you should allocate a larger hash table (using the first parameter of the '-w' switch, see above).
-z
This switch was provided to help debug A68k itself. It causes A68k to list a range of source lines, complete with line number and current location counter
value, during both passes. Lines are listed immediately after they have been read from the source file, before any processing occurs. Here are some
examples of the '-z' switch:
Technical Information
The actual symbol table entries (pointed to by the hash table, colliding entries are linked together) are stored in 8K chunks which are allocated as required. The
first entry of each chunk is reserved as a link to the next chunk (or NULL in the last chunk) - this makes it easy to find all the chunks to free them when we're
finished. All symbol table entries are stored in pass 1. During pass 2, cross- reference table entries are built in the same group of chunks, immediately following
the last symbol table entry. Additional chunks will continue to be linked in if necessary.
Symbol names and macro text are stored in another series of linked chunks. These chunks consist of a link pointer followed by strings (terminated by nulls) laid
end to end. Symbols are independent entries, linked from the corresponding symbol table entry. Macros are stored as consecutive strings, one per line - the
end of the macro is indicated by an ENDM statement. If a macro spans two chunks, the last line in the original chunk is followed by a newline character to
indicate that the macro is continued in the next chunk.
Relocation information is built during pass 2 in yet another series of linked chunks. If more than one chunk is needed to hold one section's relocation
information, all additional chunks are released at the end of the section.
The secondary heap is built from both ends, and it grows and shrinks according to how many macros and INCLUDE files are currently open. At all times there
will be at least one entry on the heap, for the original source code file. The expression parser also uses the secondary heap to store its working stacks - this
space is freed as soon as an expression has been evaluated.
The bottom of the heap holds the names of the source code file and any macro or INCLUDE files that are currently open. The full path is given. A null string is
stored for user macros. Macro arguments are stored by additional strings, one for each argument in the macro call line. All strings are stored in minimum
space, similar to the labels and user macro text on the primary heap. File names are pointed to by the fixed table entries (see below) - macro arguments are
accessed by stepping past the macro name to the desired argument, unless NARG would be exceeded.
The fixed portion of the heap is built down from the top. Each entry occupies 16 bytes. Enough information is stored to return to the proper position in the outer
file once the current macro or INCLUDE file has been completely processed.
The "high-water mark" for NextFNS is stored in char *High2, and the "low-water mark" (to stretch a metaphor) for InF is stored in struct InFCtl *LowInF.
These figures are used only to determine the maximum heap usage.
And Finally...
Please send me any bug reports, flames, etc. I can be reached on Mind Link (604/533-2312), at any meeting of the Commodore Computer Club / Panorama
(PAcific NORthwest AMiga Association), or via Jeff Lydiatt or Larry Phillips. I don't have the time or money to live on Compuserve or BIX, but my Usenet address
is [email protected] (...uunet!van-bc!rsoft!mindlink!a218).
Charlie Gibbs
2121 Rindall Avenue
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 137 of 173
Since, as far as we can tell, Charlie Gibbs is no longer maintaining A68k since 1991, you are better off filing a bug report to Kevin Kofler of the TIGCC
(TIGCC)
team: [email protected] (or [email protected])
History of A68k
Note: This section has been added to the documentation by the TIGCC Team. It was in history.txt before.
Added: Support for the "unoptimizable reloc" flag, keeping the linker from corrupting some instructions when optimizing.
Improved: All platforms now use the same maximum line length and chunk sizes.
Improved: The line count limit has been raised from 32767 to INT_MAX.
Bugfix: Fixed label(PC,Rn) addressing when "label" was in a different section (again) (reported by Julien Moutinho).
Bugfix: Fixed label(PC,Rn) addressing in all-relocs mode or when "label" was in a different section (reported by Matthieu Gallet).
Bugfix: Range checking now works correctly in all-relocs mode. (No more spurious out-of-range errors.)
Added: The -u switch now also allows unaligned code, which can be useful when the code will be copied somewhere else anyway.
Added: Short branches across hunks or object files are now allowed.
Added: -a (All relocs) switch, which tells A68k to emit all relocs, even PC-relative relocs within a section. It also emits address differences in a special
TIGCC-specific format. This will allow more aggressive linker-side optimization.
Bugfix: Increased the forward reference buffer in order to allow multiple labels at the same location, as used in PedroM.
Added: -u (Unaligned) switch, which disables automatic alignment of DC.W, DC.L, DCB.W, DCB.L, DS.W and DS.L.
Bugfix: Local labels caused a "Pass 1 / Pass 2 phase error" when preceded by an include file which contained labels, but was skipped in pass 2 (such as
OS.h).
Bugfix: The TITLE (or TTL) directive did not work at all. It now works as it is supposed to.
Bugfix: No longer crashes when trying to generate a listing file with cross-references (using the -x switch).
Bugfix: The RORG and PUBLIC directives are now recognized correctly even if the first letter is not capitalized. Thanks to Brandon Sterner for reporting
the problem with the RORG directive.
Now also accepts ";", and for the -v switch also "=", as separator in command line arguments (wherever "," is allowed), for compatibility with the "-WA,"
switch in tigcc.
Bugfix: The SUB->LEA optimisation did not change the sign of the immediate value.
Bugfix: The ADD(A)/SUB(A)->LEA and LEA->ADDQ/SUBQ optimizations caused "Pass 1 / Pass 2 phase errors" if an optimization was known to be possible
only in pass 2 (i.e. if using forward references to labels in the instruction). A68k will not try to optimize those anymore. Maybe a future version will
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 138 of 173
provide support for this kind of optimization, but it is very difficult to implement.
Bugfix: A68k did not compile correctly on Visual C++ because I had done a define in an incorrect way.
Win32 port for the TIGCC project, compiled with GCC for Mingw32.
Even though we recommend Mingw32, A68k should also compile with Microsoft Visual C++, thanks to Paul Froissart. (Please do NOT ask me questions
about compiling with Visual C++. I have just put in Paul Froissart's ifdefs.) It also compiles with Cygwin, but since the result is larger than the Mingw32
version, I do not see any benefit in using it.
Bugfix: My Win32 port of v.2.71.F3 did not support labels or variable names which contain accented characters.
Bugfix: Now detects all errors in include files. All include files will be treated in pass 2 if an error is detected.
Bugfix by Paul Froissart: fixed a random crash bug due to a missing initialization
Bugfix by Julien Muchembled: allow odd displacements for words and longwords if the resulting address might be even
The Win32 version is now less greedy with the memory, so its limitations are less annoying:
lines can now be 256 bytes long (Paul Froissart)
filenames (with path) can now be 259 bytes long (the Win32 maximum)
the default heap sizes have also been increased (Paul Froissart)
Added the following synonyms:
BLO = BCS
BHS = BCC
DBLO = DBCS
DBHS = DBCC
ROLX = ROXL
RORX = ROXR
Fixed a bug introduced by my modifications that prevented branches from being optimized in Global XRef mode.
Made A68k properly differentiate between PC-relative and absolute references to external symbols. Allowed branches to reference external labels in Global
XRef (-g parameter) mode.
Made changes so that combinations of EQU, XREF, and XDEF directives work better together. These changes were made in order for Fargo II library
linking to be easier to do.
The F1 stands for Fargo patchlevel 1.
Enforcer checks were being generated if command-line parameters that took a numeric value had no value or the value was invalid. CalcValue was
attempting to look up a label in the symbol table, which having not been allocated yet was causing a null pointer to be dereferenced. (Patrick Quaid)
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 139 of 173
Function prototyping has been added. All function prototypes are in a new include file, protos.h, which is included by A68kdef.h. Prototyping can be
disabled (for compilers which do not support it) by defining the symbol __NOPROTO; in this case old-style function declarations are generated instead.
The definition of tempstr in WriteSymTab (24 bytes) was being overrun in some cases, causing A68k to hang. Its length has been increased to MAXLINE.
(Paul Gittings, John Antonishek)
If A7 was in a list of registers in the source operand of a MOVEM instruction, all registers would be moved (i.e. the mask was set to 0xFFFF). (Risto
Kaivola)
Octal or binary values that set bit 31 were being flagged as overflow errors. (Harvey Taylor)
ORGs were unnecessarily restricted when the -s flag was specified. Everything should be absolute when S-records are generated, and any absolute ORG
should be allowed.
A new INCBIN directive has been added. It takes a single operand, a file name whose contents are included as is at the current position in the object code
file. (Julian Gold, Colin Fox)
The opcode TTL is now accepted as a synonym for TITLE.
The file mode in the creat() call in xopen() has been changed from 1 to 0644; this provides a reasonable file mode when compiled on a Unix system.
(Paul Gittings)
A new command-line keyword (-g) has been added. It causes all undefined symbols to be treated as XREF. (Paul Gittings, Steve Hawtin (who provided
the code))
All initialized fields in opcodes.c have been made global for compatibilty with more compilers. (Steve Hawtin)
The register list in a MOVEM instruction can now be an immediate operand which specifies the actual mask bits. (Paul Gittings, who provided the code)
The default value for the -q option has been changed from 10 to 100.
A new command-line keyword (-m) has been added. It must be immediately followed by a number which specifies the offset from the beginning of a
small data section to the base register specified in the NEAR directive (defaulting to A4). If this parameter is omitted, the offset defaults to 32768 bytes.
This parameter is meaningful only if the NEAR directive is used. (Colin Fox)
ORG and RORG at the beginning of the program were being processed incorrectly. (Jukka Jarvinen)
A branch instruction to its own label, e.g.
would cause phase errors; the instruction was being shortened on pass 2 but not on pass 1. (Kevin Hoare)
Labels may begin with '@' if the next character is not numeric (to avoid confusion with octal constants). (Colin Fox)
Write errors now cause A68k to terminate gracefully with an appropriate error message.
If a space is left between a file keyword and the file name (e.g. A68k -l foo.lst foo.asm) the source file was scratched. (E. Lenz)
All code using post-increment addressing in references to toupper() has been reworked to avoid post-increment. Such code does not work correctly if
toupper() is a macro. (John K. Antonishek)
The spelling of the include files A68kdef.h and A68kglb.h has been made correct as to case. This simplifies porting to case-sensitive file systems. (John K.
Antonishek)
If comments immediately follow the operands of an XDEF, XREF, or PUBLIC statement with no intervening white space (as in any of the following
statements), A68k would hang:
XDEF foo;comments
XREF bar;comments
PUBLIC blah;comments
(Bruce Dawson)
Numeric values (any radix) which do not fit into 32 bits were not being flagged. (E. Lenz)
DC statements with no operands were not being flagged. (E. Lenz)
The -f option was suggesting short branches where the displacement would be zero, which is illegal. (E. Lenz)
Branches outside the current section had the offset set to zero. (Matt Dillon, who provided a fix)
ADDI, ANDI, CMPI, EORI, ORI, and SUBI instructions whose source operand was not immediate were not being flagged. (E. Lenz)
Unary NOT of a byte or word immediate operand whose value was negative was being flagged as a size error. (John Aycock)
All forward branches were rejected when the NEAR directive was active. (Colin Fox)
Single-byte immediate operands (e.g. MOVE.B #-1,(a0)) are now padded with a high-order byte of zero, rather than being sign-extended. (E. Lenz)
The message "Error in operand format." has been changed to "Addressing mode not allowed here." in places where the latter message is more
appropriate.
If the -q option species a value of zero (or no value is given, defaulting to zero), all console output will be suppressed except for error messages, if any.
(Matt Dillon)
The 128-byte restriction on constant length no longer applies to the entire code generated by a single DCB statement; statements such as
DCB.L 64,0
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 140 of 173
Upon normal termination, A68k occasionally crashed in quit_cleanup by trying to free the relocation table twice. (Jeff Lydiatt and D. McClelland, who
worked out a fix)
MEMF_CHIP and MEMF_FAST bits were being set in the hunk length, rather than in the hunk type. (Richard Man)
BCHG.L, BCLR.L, BSET.L, and BTST.L were causing phase errors. The test to ignore the .L specification (added in version 1.21) was being skipped in pass
1 by an optimization added in version 2.4. (David Hankins)
PC-relative offset to a label was calculated as two bytes too great for MOVEM instructions. (Tony Parkhurst)
If the length code on an opcode is not .B, .W, .L, .S, or omitted, it will be flagged as an error.
JMP.S and JSR.S are flagged as errors. (Jim Butterfield)
Operands of the form (xxxx).W and (xxxx).L are now supported. This enables absolute short or absolute long addressing to be explicitly specified.
All optimization can be disabled by the new -n switch. (David Hankins)
The NEAR directive can now take a single operand, which can be any address register (or equated symbol) except A7. If omitted, the register defaults to
A4.
Instructions of the form BTST Dn,#nn are no longer flagged. This obscure variant is nonetheless legal.
Small code/data conversion was sometimes taking place when no NEAR directive was active. (Jeff Lydiatt)
If comments immediately followed the operands of a DC statement with no intervening white space, A68k would hang. (Ulf Nordquist)
In the following command:
the space between the -w and 15000 would cause A68k to look for a source file called "15000", and to think that the object file is to be called
"myprog.asm". When it can't find "15000" it would display an error message and scratch "myprog.asm". (Jeff Lydiatt)
If an INCLUDE file that is skipped on pass 2 contains a macro call, subsequent uses of \@ (macro sequence number are subsequently flagged. The macro
counter must be bumped along with the line number when skipping an INCLUDE. (Colin Fox, Harvey Taylor)
Even though a macro definition was being skipped by IFxx/ENDC, its ENDM directive was still being detected, causing spurious diagnostics. (Harvey
Taylor)
NOP was not being recognized. When moving all directives into the opcode table, NOL and NOLIST were placed after NOP, rather than before. (Colin Fox)
Symbols defined in the current module and declared as PUBLIC were not being written to the object code file when -d was specified. (Colin Fox)
Conversion of 0(An) to (An) (implemented in version 1.2) was causing errors in the MOVEP instruction, which requires a displacement even if it is zero.
This conversion is now disabled for MOVEP instructions.
User macros containing invalid opcodes caused A68k to get lost when returning to the outer source file. (Colin Fox)
Large values of -w (over 6000 or so) would cause a visit from the Guru. The work field in HashIt was overflowing and going negative. Changing it to
unsigned corrected the problem. (Colin Fox)
Although user macros are no longer displayed when -q is a negative number, the calling file's name was still being displayed at the end of the macro.
All file I/O has been rewritten to use level 1 I/O (open, creat, close, read, write, and lseek) instead of level 2 I/O. A68k now does its own buffering and
unbuffering to reduce system overhead and increase speed. (Bruce Dawson)
All assembler directives have been incorporated into the opcode table. Since the opcode search now looks up directives as well, speed is increased.
Miscellaneous code optimization for additional speed.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 141 of 173
Macro definitions within an INCLUDE file were disabling the test for skipping the file on pass 2.
Errors encountered in an INCLUDE file on pass 1 were not disabling the skip of the file on pass 2 - the pertinent error messages could not appear.
XDEF information and optional symbol table dumps were not being written to the object code file for any hunks that did not contain relocatable code or
data. (Colin Fox)
If the -q option is specified as a negative value, user macros are no longer included in line number displays, reducing clutter.
Some source code has been re-arranged to reduce size.
Macro definitions that span two chunks of memory were causing garbage and probably a crash when the macro was being expanded. Pointers were not
being handled properly when linking the two chunks.
Statements such as EQU and SET were not being flagged as illegal forward references if referencing a label defined on the same line, e.g.
The position within macros and INCLUDE files was sometimes out by one line when reported in error messages (and the new feature of the -q switch).
If the -q option is specified as a negative value, line numbers will be displayed as positions within the current module (whose name is also displayed),
rather than a total statement count. (Bruce Dawson)
INCLUDE files can be skipped on pass 2 even if they contain SET statements - the values of all symbols SET in the INCLUDE file are stored (as at the end
of the file) in a separate table and are patched when the INCLUDE file is skipped. (Bruce Dawson)
The last digit of the statement number display (lengthened in version 1.24) was not being erased before displaying error messages.
A68k would go into a loop if a user macro was missing an ENDC directive. This error is now flagged (see below).
The highest statement number displayed at the end of each pass is now left on the screen. This means that, at the end of pass 1, you can always see how
many lines A68k will have to process in pass 2, giving an idea of how how much longer you have to wait. (Colin Fox)
The symbol table is now built using a hashing algorithm. This eliminates the slowdown that occurs in pass 1 as the symbol table grows, due to the old
insertion process. (Bruce Dawson)
If A68k terminates abnormally for any reason (such as insufficient memory) the object file is scratched (unless the -k option is set). (Bruce Dawson)
Any INCLUDE files which cannot be found are flagged as errors in pass 1, and the assembly is aborted at the end of pass 1. (Bruce Dawson)
Missing ENDC directives are flagged in macro expansions. Also, missing or unpaired ENDC directives in user macros are flagged.
If an INCLUDE file doesn't generate any code and no listing file is required, it won't be read again in pass 2. The statement numbers will be bumped to
keep in proper alignment. This can really speed up assemblies that INCLUDE lots of equates. (Colin Fox)
MOVEA to a data register was not being flagged, even though all other invalid addressing modes were.
Attempts to ORG out of the current hunk (including to an absolute address) were not being flagged. (E. Lenz)
If the size of the bottom of the primary heap (symbols and macro text) exceeded 32K, any further macro definitions would expand as endless garbage.
(Colin Fox)
If the size of the bottom of the primary heap (symbols and macro text) exceeded 64K, any further external symbols (XDEF) would be flagged as
relocatability errors upon each reference. (Colin Fox)
Where statement numbers are displayed as fixed-length fields, their maximum length has been increased from 4 digits to 5. (Colin Fox)
The PUBLIC directive has been implemented. As with the Aztec assembler, any labels defined as PUBLIC will be treated as XDEF if defined within the
current module, and XREF otherwise. (Jeff Lydiatt)
The test for a third operand was producing erroneous error messages on instructions whose second operand was in immediate mode. The '#' was not
being taken into account, since it is not copied to DestOp.
Expressions of the form R-A, where R is a relocatable term or expression and A is an absolute term or expression, were being flagged as relocation errors.
This was due to a bug in the routine which should (but did not) flag expressions of the form A-R. (David Ashley)
Instructions with three operands were not being flagged as errors. This can be caused by an extra comma being typed in the instruction, as in:
BTST #0,state+3,(a5)
Excess spacing has been removed from the listing file. These changes are similar to those already made to the console output (probably at about version
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 142 of 173
1.05).
If the first statement in the source file is TTL or PAGE, an empty page is no longer produced at the start of the listing.
The instruction
BTST.L #8,D0
had a long-word value generated for the bit number. This bug also applies to BSET, BCLR, and BCHG. The .L specification is now ignored. (Ulf Nordquist)
A reference to the label of the current instruction was being converted to PC-relative on pass 2 but not on pass 1. This was causing phase errors. The
label hasn't been added to the symbol table at the time the instruction is processed. Conversion to PC-relative addressing will now not be attempted in
this case, although references to * can and will be converted.
All string-type DC statements, regardless of length, were being treated as DC.B. For example, DC.L 'A' would generate only one byte of object code.
(Gerald Hull)
DC.W and DC.B statements were not being checked to ensure that their values would fit into a word or a byte respectively.
If a comment line had white space preceding the asterisk, A68k would hang. Actually, it was interpreting the asterisk as an opcode and trying to open a
macro file called "*". Since under AmigaDOS such a file is the console, A68k was actually waiting for console input.
If an instruction with no operands (such as RTS or NOP) followed MOVE.L #rel,D0 where "rel" was a relocatable symbol, the RTS (etc.) would have its
nonexistent operands flagged as invalid.
SECTION names enclosed in quotes were not being handled correctly.
Source modules that did not generate any code, data, or BSS areas, but only defined symbols, such as
label equ 4
xdef label
end
Jeff's experimental hunk code (prefixing hunk names with a sequence number before adding to the symbol table) has been permanently incorporated. It
seems to work better with BLink on programs that have hunks continued farther on in the source code. (Jeff Lydiatt)
The macro parameter \0, which is replaced by the size specification in the macro call (B, W, or L, defaulting to W) is now supported. (Gerald Hull)
Operands of the form 0(An) will be treated as (An). (Bruce Dawson)
If an instruction with no operands (e.g. RTS) followed a MOVE.L #label,D0 the RTS would be flagged with a relocatability error. Src.Mode and Dest.Mode
were not being cleared. (Colin Fox)
A68k would go into a loop while processing the arguments of a macro call, if these arguments are followed by comments separated from the arguments
by one or more tab characters, and the -t switch is specified on the command line. All tests for blanks have been replaced by calls to isspace().
The operand alignment checks added in version 1.06 were erroneously testing the following instructions:
BCHG
BCLR
BSET
BTST
NBCD
Scc
TAS
These instructions are now exempt from alignment checking.
A listing file name can now be specified with the -x switch; it is no longer necessary to specify both the -l and -x switches to produce a cross- reference
listing with a name other than the default.
DS statements with more than one operand are flagged and ignored (in case they should be DC).
A character string used as a numeric value is flagged and set to zero if it is more than four characters long.
BSS sections were not being written to the object code file except for a BSS section at the end of a program. This is due to a bug in the code added in
version 1.05 to overwrite null sections.
If a source module contained a mixture of lengths (8, 16, or 32 bits) in external references (XREF) to the same label, all references were being treated as
if they has the length of the first reference.
DS operands that are either a forward references or relocatable are now flagged.
Short branches (Bcc.S, including BRA and BSR) to the next instruction (i.e. a displacement of zero) are illegal - the processor takes the displacement from
the next word. Attempts to generate a short displacement of zero are now flagged.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 143 of 173
Instructions that take no operands (such as RTS) were being flagged if they had comments that were not preceded by a semicolon.
Strings and character values may be delimited by either apostrophes (') or quotation marks ("). The character not used as a delimiter can be used within
the string without doubling it. For example,
The object code file will be scratched if any errors were found, unless the -k (keep) flag is set. (Bruce Dawson)
The symbol .A68K is automatically defined at the beginning of each assembly as a SET symbol with an absolute value of 1. This enables programs to
check whether they're being assembled by this assembler. (Jeff Lydiatt)
The symbol table insertion routine has been greatly speeded up.
Lines skipped by IFxx/ENDC were not being counted in the line number given in error messages.
DATA and BSS sections may be unnamed, or have names the same as CODE sections. Honest, I thought section names had to be unique even across
types.
CHIP and FAST options on the CODE, DATA, and BSS synonyms for the SECTION directive were not being handled correctly.
XDEF records and symbol table records (if desired) were not being produced for symbols defined ahead of the first object-code producing instruction.
The CNOP instruction can now force alignment relative to any boundary up to 128 bytes. The second operand must still be a power of 2.
The -q switch has been added to change the frequency with which progress reports (current line number) are displayed on the console. The default
remains at every 10 lines (-q10). If you specify -q (no interval) or -q0 the line number displays will be suppressed. This will make assemblies run slightly
faster due to reduced console I/O. (Bill Henning)
The -t switch has been added to keep any tabs in the source file when producing the listing file, as well as generating tabs elsewhere whenever possible.
This speeds up assemblies and gives smaller listing files, but such listing files cannot be displayed on devices that do not assume a tab stop in every 8th
position. (Bruce Dawson)
Any single-operand instruction with two operands, and any no-operand instruction with any operands, will be flagged.
Relocatable 8- or 16-bit immediate operands will be flagged. They blow up BLink.
Named local labels are now supported. Their names are formed in the same way as normal labels, but are then preceded by a backslash. Their scope is
the same as normal local labels (nnn$). (Colin Fox)
An alignment error will be flagged in the following cases:
Odd displacement on a LINK instruction
Bcc or DBcc to an odd address
In any word or long-word instruction, any operand using the following addressing modes:
Address register indirect with displacement
Address register indirect with index and displacement
Absolute short
Absolute long
Program counter indirect with displacement
Program counter indirect with index and displacement
LEA and PEA instructions are exempt from these tests.
If a section is found to contain no data, A68k will back up to its beginning and overwrite it with the next section. The result is that null sections will no
longer appear in the object file.
SECTION prog,CODE
<code>
SECTION variables,BSS
<DS statements>
SECTION prog,CODE
<more code>
bad relocation information was being generated for the continuation of the SECTION. This bug was left over from version 1.03.
All console output except for error messages is now sent to stderr - this enables stdout to be redirected, producing an error file.
Console (stderr) output has been modified to require fewer lines on the screen.
If an error occurs while expanding a macro or INCLUDE file, the position of the call in each outer file is given along with the position in the current
(innermost) file. Tracing continues until the outermost file (i.e. the original source file) is reached.
MOVE was being converted to MOVEQ regardless of operand size - this conversion is legal only for longword MOVEs.
Modifications to version 1.03 caused bad relocatable entries to be generated.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 144 of 173
xdef label
bra label
.
<at least 128 bytes of object code>
.
label:
(The XDEF was fooling A68k into thinking that "label" was defined within 128 bytes of the BRA instruction on pass 1, although on pass 2 it knew better.
If the first operand of an two-operand executable instruction contained a character term containing a left or right parenthesis, it would generate error
messages and be incorrectly evaluated.
Labels that don't begin in column 1 (denoted by a trailing colon) caused a Guru Meditation.
Certain ADD and SUB instructions using PC-relative addressing may cause phase errors. If the displacement is in the range 1 to 8 inclusive, the
instruction was erroneously converted to ADDQ or SUBQ during pass 2.
The -z option has been added to display the current source program line on stdout as it is read, optionally over a given range. This feature is provided for
debugging purposes.
Bcc, BSR, and DBcc to labels in other than the current section is now supported. A 16-bit relocation entry will be generated for each such reference.
PC relative mode will be generated for backward references to labels within the current CODE section if legal for the current instruction. Forward
references will not be converted, since there is no way of telling which section the label is in during pass 1.
The cumulative sizes of all sections by type (i.e. CODE, DATA, and BSS) will be displayed at the end of the listing file and the console display. (Bruce
Dawson)
In the symbol table dump, section names will no longer be indicated just as SECTION, but rather as CODE, DATA, or BSS, depending on type.
A header file is now supported. If the parameter -h<filespec> is included on the command line, the specified file will be included as if the source file's first
line was " include <filespec>". The file specification may include a path name, although the include path names given by the -i parameter (if any) will also
be searched.
An equate file can now be produced. If the parameter -e<filespec> is included on the command line, a file will be written containing EQU statements for
any symbol whose value is absolute. If -e is specified without <filespec>, the name of the file will be formed in the same way as the list file, except with
an extension of ".equ". (Bruce Dawson)
No symbol table dump will be produced unless the -x (cross-reference) switch is set. Formerly a symbol table dump was always produced, with only the
cross-reference portion optional.
Long-word constants and storage areas were being aligned on a double-word boundary. The only place where double-word alignment is now forced is at a
break between SECTIONs, since the length of an AmigaDOS hunk must be a multiple of 4 bytes. (CNOP 0,4 can still be used if double-word alignment is
desired by the programmer.)
If a label on an END statement or the first statement of a SECTION was named in an XDEF statement, it would not be written to the object code file. The
latter case includes both the label of a SECTION directive and the label of the first executable instruction in the absence of any SECTION directives
(defaulting to an unnamed CODE section). In the final case (default unnamed CODE section), references to XREF symbols in the first statement would
also not be written to the object code file.
If the last statement in the source file was not terminated with a newline character (premature EOF), it was being ignored altogether.
A register list as the source operand of a MOVE instruction was not being flagged as an error. (MOVE to a register list was being flagged, however.)
MOVE from USP was generating incorrect code. Also, MOVE from SR or CCR to an address register was generating incorrect code rather than being
flagged.
This is the documentation of the TIGCC linker, the tool that reads the compiled and assembled files and merges them into a single program. Most parts of this
documentation only need to be read by experts; you may safely skip over all parts that you do not understand.
The purpose of a linker is to take executable code and data from different files and merge it into a single program. It must resolve dependencies between the
files, and there are many architecture-dependent features linkers are required to support. The complicated part about linking is that binary code can be
encapsulated in different formats; most linkers, including the TIGCC linker, can import code from several formats and export it to yet another one (see TIGCC
Linker File Formats).
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 145 of 173
The TIGCC linker can handle two kinds of files: object files and archive files. Object files are produced by the compiler or assembler. They contain the code and
global variables of the program; all object files passed to the linker are processed and then included in the final output. Archive files, also known as static
libraries, are collections of object files. An archive member is included only if this is requested by another file.
Files can reference each other via text strings called symbols. These symbols are usually labels in assembly code, or functions and global variables in C code.
The most popular way of referencing symbols is to ask that the final address or offset of a specific symbol be inserted at or added to a specific location in the
code. This is called relocation.
When the linker is executed, it first reads all object files passed to it and imports their contents into its internal data structures. Then it tries to resolve the
references to symbols defined in another file. If a symbol cannot be resolved, it is looked up in the symbol tables of all archive files passed to the linker; if it is
still not found, this is an error. Archive members are imported immediately if required, and they may reference symbols defined in other files as well. Some
special actions are performed based on the contents of the imported files, code and data blocks (sections) are sorted and merged if required, and offsets
between different locations in the code are inserted whereever the object files requested this. Finally, the program is exported to an executable file.
The TIGCC linker is available in two forms: As a standalone command line program or as a dynamic link library (DLL). TIGCC uses the DLL version for improved
speed and to avoid maintainance problems, but experienced programmers might want to use the command line version in some cases because it is a little more
advanced.
In the IDE, linker options can be set in the project settings. The tigcc command line compiler accepts most of the options of ld-tigcc and passes them to the
linker.
In ld-tigcc, options and input files may appear in any order in the command line. Input files may be either object or archive (static library) files. They are
handled differently depending on the type of the file: Object files are read completely in the order they are supplied; archive file members are read only if the
program references a symbol they export. If multiple archive files export the same symbol, ld-tigcc uses the archive that is supplied first.
Output file names and variable names are usually set according to the name of the first object file in the command line, but they may be changed using the '--
output' and '--varname' options described below. The file extensions depend on the exact output format used; they are usually what the transferring software
expects them to be.
-h
--help
Print a short description of all available options.
--version
Print the version number of the tool and a short copyright notice.
-v
--verbose
Print statistics about the linked program before terminating. These include the target calculators, program variable name and size, data variable size, BSS
size (size of all uninitialized global variables), the total number of absolute relocs, the number of relocs which appear in the native format of the target
OS, and optimization possibilities or results. In the IDE, these statistics are displayed automatically, unless this is turned off in the preferences or the
program is run automatically after successful linking. If the linking process fails, no statistics are shown.
--dump
Display all dumps of the program contents during the entire linking process. For details about dumps, see ld-tigcc Program Dumps.
--dumpn
Display the n-th dump of the program contents. For details on the different linking stages and the associated dump numbers, see ld-tigcc Program
Dumps.
--native
Use TIGCC native mode by default. Without this option, the linker starts in kernel mode (for compatibility with existing programs), but this may be
changed using special symbols (see Symbols to Control the Linker). For more information about modes, see TIGCC Linker Modes.
--fargo
Use Fargo II mode and compile for the TI-92. This option is only available if Fargo support is compiled in. It exists for compatibility with existing Fargo II
programs, which do not explicitly specify a mode and a target calculator.
--flash-os
Use Flash OS mode. This mode creates an unsigned Flash operating system upgrade for the TI-89, TI-92+ and Voyage 200 calculators. (TI-89 Titanium
Flash upgrades are currently not supported.) This option is only available if Flash OS support is compiled in.
--remove-unused
Remove unused sections. If a section is not referenced by another section, this option causes it to be removed. Startup sections are never removed;
neither is the first section in Nostub mode. Note that in some cases, the linker cannot determine whether a section can be removed before merging it with
another section; in this case, it is not removed even though it may not be referenced at all.
--optimize-relocs
Update the destination symbol of relocation entries to the nearest available symbol, thereby making the offset as small as possible. This improves the
readability of dumps and some diagnostic messages, but should not have any other effect than this.
--optimize-code
Perform all code optimizations, including NOP, return, branch, move, test, and calculation optimization. Note that it is possible for code optimization to
create invalid code or accidentally change data instead of code. The probability is not very high, so you should really enable code optimization at least
partially, but if your program crashes for no apparent reason, try turning off code optimization. For more information about optimization, see TIGCC
Linker Binary Code Fixup.
--optimize-nops
Perform NOP instruction removal.
--optimize-returns
Perform return sequence optimization.
--optimize-branches
Perform branch optimization.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 146 of 173
--optimize-moves
Perform move/load/push optimization.
--optimize-tests
Perform compare/test optimization.
--optimize-calcs
Perform calculation optimization.
--cut-ranges
Optimization has two effects: It can reduce the number of relocation entries, and it can make instructions smaller. Usually, the space gained from making
the instructions smaller is filled with NOPs. If this option is used, the linker will attempt to cut out these ranges of code instead, making the size of the
executable even smaller. This only works for input files that were assembled in all-relocs mode, but this is handled automatically if this option is used via
the tigcc front-end or the TIGCC IDE.
--reorder-sections
Reorder sections to make references shorter. The fixups (see above) can then fit those shorter references into smaller and faster addressing modes, so
using this option can improve both size and speed. It can also allow the fixups to remove relocations or to turn F-Line jumps into faster branches. Since
computing the optimal reordering is NP complete and very expensive in practical terms (the factorial of the number of sections is a huge factor), section
reordering is implemented through heuristics. Therefore, the result is not guaranteed to be optimal. There are rare cases where section reordering can
still take exponential time, these are due to hardcoded short references between sections rendering some reorderings impossible. In this case, the linker
will emit warnings as impossible reorderings are encountered so you can follow the process, or stop it (and go fix your program, hardcoded short
references between sections are not a good idea, that's what linker optimization is for!) if it takes too long. Startup sections can be reordered only with
other startup sections with the same startup number. Non-startup sections can be reordered only with other non-startup sections. Sections which are
emitted separately (e.g. a dynamically allocated BSS section or a data section in an external file) cannot be reordered at all.
--merge-constants
Merge identical constants (including strings) to avoid duplication. Constant merging works on all symbols (actually, the ranges included within 2 symbols,
where symbols at the same position are considered the same symbol) in sections marked mergeable. Constants can be merged if they are identical or if
one of them is a prefix of the other. This can be used by the compiler to avoid duplicating string literals (and, if desired by the user, other constants) in
multiple object files. Unaligned and aligned sections are distinguished to keep the linker from accidentally breaking the alignment while merging aligned
constants with unaligned ones which happen to contain them as a prefix.
--omit-bss-init
Skip the initialization of the BSS section, which holds uninitialized global variables. Older versions of TIGCC never initialized the BSS section, so many
older programs do not rely on the initialization. If you use this option, you must be sure that there is really no code that relies on the initialization of
global variables to zero (which means, among other things, that you have to use the compiler option '-fno-zero-initialized-in-bss'). For a safer
alternative, try the __ld_omit_bss_init control symbol.
--outputbin
Instead of creating a wrapped calculator variable that includes a folder and variable name, a checksum, and some extra information, write only the raw
contents of the variable to the file. The file extension is changed in a way that allows different files to be generated for each target calculator but prevents
confusion between raw and wrapped data.
-o file
--output file
Write the output to the file named file.ext, where ext is the extension that fits the file type. file may include a path, but if it includes its own extension, ext
will be appended anyway. This also sets the variable name to something that resembles file as closely as possible. Note that it does not do any error
checking on the characters of the file parameter.
-n [folder\]name
--varname [folder\]name
Include the folder name folder (main if unspecified) and variable name name in the wrapper file. If the file is not wrapped (i.e. if '--outputbin' has been
specified), this option has no effect.
-d [folder\]name
--data-var [folder\]name
Exclude all non-executable data (global variables) from the program and create an external variable for it. Note that you are absolutely required to make
sure that no code is executed from the data section; otherwise it will crash depending on the calculator model: Newer calculators have a protection device
that lets the operating system restrict the areas code can be executed from. name is the variable name to be assigned to the data variable. folder defines
the folder of the variable; if it is not specified, the folder from the '--varname' option is used.
--data-var-copy=condition
Defines when to create a copy of the data variable in RAM. If condition is always, the program will always work on a copy in RAM, which means that you
may rely on the data being the same on every start of the program. However, if the data variable is not archived, you may easily run out of available
memory. archived causes a copy to be created only if the data variable is archived; this is the default. If the variable is not archived, the program will
work on the actual contents of the variable, so the values of all global variables will be kept even after the program finishes. never tells the linker to work
on the original variable unconditionally, but since you may not write to the archive memory, you have to make sure that you never modify the value of a
global variable. If the '--data-var' option is not specified as well, this option has no effect.
The ar-tigcc tool can be used to create archives recognized by ld-tigcc. The output format is the format used by GNU ar, for which this tool is a
replacement. This allows for maximum compatibility between archives and programs created with different versions of TIGCC.
In ar-tigcc, options and input files may appear in any order in the command line. Input files can have any file format; they are simply written into the archive
in the order specified in the command line. However, object files whose format is recognized are searched for exported symbols, so that ar-tigcc can create a
symbol table for the archive.
If no output file name is specified, ar-tigcc uses the name of the first input file and appends a '.a' extension to it. It is highly recommended that you specify
a different name with the '--output' option.
-h
--help
Print a short description of all available options.
--version
Print the version number of the tool and a short copyright notice.
--dump
Display a small dump of the archive file contents. This includes the members as well as the symbols they export.
-o file
--output file
-rc file
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 147 of 173
-qc file
Write the output to the file named file. Unlike ld-tigcc, ar-tigcc does not append a file extension to file. '-rc' and '-qc' are recognized for compatibility
with GNU ar, so that certain command lines work with GNU ar as well as ar-tigcc.
--no-names
Omit the file names of the input files in the archive. The archive will only contain names of the form fln.o, where n is the index of the file starting at 1.
Omitting file names may be a good idea, especially if you use long file names, since the traditional archive format imposes a maximum of 15 characters
on the length of file names. Otherwise, if a file name exceeds this maximum, it will be cut off at the 16th character. The IDE and the tigcc command line
compiler always use this option.
A linking mode defines how the linker treats the contents of the program after they have been read from the object files. The TIGCC linker has several different
modes; some of them are related to specific output file formats, and some of them are present only for historical reasons.
The recommended mode for normal TIGCC programs is TIGCC-native mode. It is the simplest mode; the program is basically an empty sheet of paper, which
can be filled with code of all sorts. The default mode is actually kernel mode unless you set the appropriate command-line option, to make existing programs
work without modifications.
This mode (which can be enabled using the '--native' command-line option or the control symbol _tigcc_native) is the recommended mode for all new
programs. When operating in this mode, the TIGCC linker does not process the program in any special way, except that it requires the definition of at least one
startup section. The idea is that stub code should not be handled by the linker itself but rather included manually by the program as needed. However, every
program (regardless of the architecture and operating system) needs to have a prolog that either contains the location of the main entry point or is itself the
startup code of the program. On the TI platforms with official assembly program support, execution always starts at the beginning of the program, so the prolog
is actually the startup code.
Ideally, every program should be able to use this mode. However, at the moment, the output file format cannot be specified other than by switching to the
appropriate mode. If you want to use a different output file format than the default TIOS format (i.e. Nostub DLL or Fargo II), you cannot use TIGCC-native
mode. At the moment, adding support for explicit selection of the output file format does not have any particular benefit, since it does not permit the removal of
any of the other modes. However, as soon as the need for another output format (e.g. raw) arises, there should be a command-line option to select the format.
If this mode is activated using the _nostub control symbol, execution will start at the very beginning of the program. The exact entry point depends on the
order of the object files as passed to the linker as well as the order of the sections inside an object file. Because of this insecurity, this mode should never be
used in new programs. Programs written in assembly should define a small startup section including a jump to the actual main function and use TIGCC-native
mode instead. If the main function follows immediately, the jump can even be optimized away by the linker.
If a startup section is defined in nostub mode, the linker emits a warning and switches to TIGCC-native mode. This ensures that nostub mode really means that
no stub is added to the program.
If the linker is told to use Nostub DLL mode using the __nostub_dll control symbol, it acts like in TIGCC-native mode, except that it causes the linker to use the
Nostub DLL output format instead of the default output format. Since the stub for nostub DLLs is defined as conventional C code rather than imported as a
startup section, this mode does not require the definition of a startup section.
In this mode, which is enabled by default, the linker acts the same way as in TIGCC-native mode, but it creates a global import asking for the appropriate
kernel format header. See Automatically Created Global Imports for more information.
This mode is used to create a program that can be run on a TI-92 with Fargo II installed. It can be turned on using the '--fargo' command-line option or the
_fargo control symbol. It uses the Fargo II output format, which is binary data wrapped in an empty TI-BASIC program. It creates a global import asking for the
appropriate Fargo II header (see Automatically Created Global Imports for more information). And it also causes the value of __ld_entry_point to be decreased
by two, to point to the two size bytes in the TIOS file format rather than the beginning of the program data.
This mode creates an unsigned Flash operating system upgrade for the TI-89, TI-92+ and Voyage 200 calculators. (TI-89 Titanium Flash upgrades are currently
not supported.) It can be turned on using the '--flash-os' command-line option or the _flash_os control symbol. It currently supports only the raw TIB output
format, which is enabled by the '--outputbin' option. Support for the current 89u/9xu/v2u format is planned and will be the default. It creates a global import
asking for the appropriate Flash OS header (see Automatically Created Global Imports for more information). Since Flash operating systems are composed of 2
discontiguous parts, a small (24 KB) startup segment and a large (1944 KB for 2 MB FlashROMs, 3992 KB for 4 MB FlashROMs) main segment, startup sections
are handled in a special way in this mode: Startup sections are placed into the startup segment, all other sections are merged into the main segment.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 148 of 173
The TIGCC linker recognizes several file formats. Currently, it can import COFF and AmigaOS files and export TIOS ASM files, Nostub DLL files (which are TIOS
custom files with a special format), and Fargo II files (which are TIOS PRGM files with special hidden data). A small overview of the capabilities of each format
is described in the following table:
In addition to options specified in the command line, the TIGCC linker can be controlled using special symbol names. They should be used directly only in
assembly programs; C programs should rely on the appropriate library facilities if they are available.
__ref_all_...
_tigcc_native
_nostub
_nostub_dll
_fargo
_flash_os
_library
_ti92, _ti89, _ti92plus, _v200
_flag_...
_version...
...@version..., ...__version...
__ld_use_fline_jumps
__ld_use_4byte_fline_jumps
__ld_omit_bss_init
__ld_ignore_global_imports
labels;
undefined exported symbols;
imported (used but undefined) symbols;
common symbols.
Not all assemblers support all types of symbols; for example, the A68k assembler does not support exporting symbols which are not defined somewhere in the
same file. This assembler is also somewhat special from the linker's point of view: It only outputs exported and imported symbols by default; local labels can be
supplied in a symbol table, but since it is optional, the linker does not use it to receive control information.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 149 of 173
If a symbol is detected as a control symbol, it is not imported into the internal data structures as usual. There are two reasons for this: First, if a user
accidentally defines a control symbol somewhere (some traditional control symbol names are quite short), the resulting error can help detect this problem.
Second, if common symbols are used, they would waste space in the executable otherwise.
__ref_all_...
Defining __ref_all_name creates a global import for all symbols named name. Importing the same symbol twice does not have any particular effect; however,
sometimes this is necessary if you want a global import to succeed as early as possible.
If none of the archives supplied to the linker exports a symbol with this name (or a related name using conditional reaction), the linker outputs a warning.
_tigcc_native
Defining this symbol switches to TIGCC native mode. We recommend that you define this in all new programs, and then create or import startup sections.
_nostub
Defining this symbol switches to NoStub mode. It can only be used in assembly files, since it is impossible to guarantee for some code to be at the beginning of
the file.
_nostub_dll
Defining this symbol switches to NoStub DLL mode and tells the linker to compile a library instead of a program. If NoStub DLL support is not compiled in, the
symbol is not treated in a special way.
_fargo
Defining this symbol switches to Fargo II mode. If Fargo support is not compiled in, the symbol is not treated in a special way.
_flash_os
Defining this symbol switches to Flash OS mode. If Flash OS support is not compiled in, the symbol is not treated in a special way.
_library
Defining this symbol causes a library to be created instead of a program. The linker will warn about program startup sections being included, and depending on
the linking mode some different automatic global imports will be created.
You need to define one or more of these symbols to specify the calculator for which the program is to be linked. This only controls which output files are
created; the linker does not check whether a file format really exists for a given calculator. Kernel compatibility flags (see _flag_...) are added according to the
symbol:
_flag_...
Defining _flag_n sets the n-th bit in the kernel compatibility flags. Some flags are reserved for calculator compatibility information (see here); the others can be
used to pass additional information to the kernel. Note that the meaning of a particular flag may vary between kernels. Kernel flags occupy a single byte;
therefore the range of n is 0 through 7.
_version...
If you define the symbol _versionver, the program/library version number is set to ver, interpreted as a hexadecimal value. Note that the kernel format limits
the reserved space for the version number to one byte; this means that kernels only accept two digits for ver.
...@version..., ...__version...
To specify a required minimum version number for a library used by the program, you can define lib@versionver or lib__versionver. lib is the name of the
library (see Library Calls); ver is the minimum version number to be accepted, interpreted as a hexadecimal value (see _version...).
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 150 of 173
__ld_use_fline_jumps
Defining this symbol tells the linker to use relative F-Line branches for branches which would otherwise need to be absolute. These are supported by AMS 2.04
or higher and by various F-Line emulators, including TIGCC's own emulator.
__ld_use_4byte_fline_jumps
Defining this symbol tells the linker to use program-relative F-Line branches for branches which would otherwise need to be absolute. These branches are 4
bytes long, whereas normal relative F-Line branches have a size of 6 bytes. However, since they are relative to the program's entry point, the program must
install its own emulator to handle them.
__ld_omit_bss_init
Defining this symbol in a source file tells the linker that this file does not depend on the initialization of the BSS section to zero. The result is that all
uninitialized global variables defined in that file may contain garbage at the beginning of the program. This does not guarantee that the initialization is skipped;
in fact, if at least one file needs the initialization, it is easier to initialize even the variables that were declared to not need it.
For pointer-based object file formats (such as COFF, the format used by the GNU tools included in TIGCC), this symbol really affects all variables in the file it is
defined in. For sequential formats (such as the AmigaOS format used by the A68k assembler), it affects only the parts that follow the symbol. Since BSS data
usually appears at the end of the object file, this restriction should not have any effect.
Note: If you define this symbol, you should use the compiler option '-fno-zero-initialized-in-bss'; otherwise even variables explicitly initialized to zero will
contain garbage.
__ld_ignore_global_imports
Defining this symbol in a source file tells the linker that from this file on, defining a __ref_all_... symbol has no effect. This should not be used except in very
special circumstances.
Startup Sections
The concept of startup sections is unique to the TIGCC linker. It only makes sense in low-resource environments like calculators. The idea is that a file that is
imported should be able to specify that it needs certain code to be executed at the beginning of the program. Usually, there are two approaches to address this
situation: constructors and main function wrappers.
If constructors are used to handle this, a lot of memory is wasted: A constructor table needs to be created with appropriate code to handle its contents; every
item needs to save all registers except a few, and sharing data between two constructors requires global variables. Moreover, using constructors, it is not
possible to specify the order in which startup code is to be called; however, parts of the startup code often need to rely on other parts to be executed first.
Main function wrappers appear in almost every environment. But since these wrappers are fixed, they need to handle all startup code that might possibly be
needed, instead of letting each file choose its own startup code. For example, such fixed startup code would need to handle exceptions even if the program
never generates them, or fill certain global variables that are never read.
Startup sections are actually a wrapper around the main function, but they can achieve even more flexibility than constructors: They are numbered and
executed in the exact order specified by the numbers, and no extra code is executed between two consecutive startup sections, so registers can be used to pass
data between two sections.
Startup sections can be used not only to insert code at the beginning of the program, but also to generate the required headers for certain file formats.
Sometimes this is easier than writing the linker code to insert the required headers (see TIGCC Linker File Formats).
Since libraries may need to contain a header, some stub code that is called when the user tries to execute the library, and possibly some startup code, they
may also have startup sections. However, it does not really make sense to include a startup section designed for a program in a library. Therefore, there are
library startup sections, which may appear in both libraries and programs, and program startup sections, which may appear only in programs. Library startup
sections are always included before program startup sections.
Startup sections are detected based on their name. To declare a program startup section, name the section _stn, where n is a value from 1 to 99999 (higher
values for n may be accepted if the object file format supports section names longer than 8 characters, but it is not recommended to use them). To declare a
library startup section, name it _stln, where n is a value from 1 to 9999 (higher values are not permitted). Startup sections are included in ascending order; if
two startup sections use the same index, their order is undefined.
Global Imports
Just like startup sections, the concept of global imports is unique to the TIGCC linker. Global imports and startup sections are closely related to each other: It is
best to keep startup sections in archive files, so they can be imported as needed, but the existing method of importing archive file members does not work.
Usually, an archive file member is imported if a symbol it exports is referenced in a relocation entry. However, code that requires a specific startup section to be
included does not necessarily reference any of the symbols in the corresponding archive member; it just needs the startup code to be there. A global import
solves this problem by importing an archive member without inserting its address anywhere.
Actually, a global import imports all archive members that export the symbol referenced by the import (and even more, see Conditional Reaction to Global
Imports). If no archive member exports this symbol, a warning is emitted. This way, it is very easy to create archive files that react to multiple imports; for
example:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 151 of 173
A global import for A would cause the files 1 and 3 to be included in the program. If it could only import one file, 6 files would be needed to get the same result:
File 1 exports the symbol A and creates two global imports for File4 and File6.
File 2 exports the symbol B and creates two global imports for File4 and File5.
File 3 exports the symbol C and creates two global imports for File5 and File6.
File 4 exports the symbol File4.
File 5 exports the symbol File5.
File 6 exports the symbol File6.
Global import can be created using the __ref_all_... control symbol. Some global imports are also created automatically by the linker on certain conditions.
Sometimes, it is convenient for an archive member to react to a global import differently than just to be included whenever the import is created. For example,
a startup section may be optimized better if a certain register already holds a certain value, otherwise it must compute the value by itself. The TIGCC linker
defines two symbol operators for this purpose:
..._AND_...
NOT_...
To be included only if the global imports A and B are defined, a file must export the symbol A_AND_B. To be included only if the global import A is not defined, a
file must export the symbol NOT_A. Symbol operators may be combined, i.e. a file exporting NOT_A_AND_B is included only if no global import A exists, and a
global import B is defined.
There is a small quirk related to negated conditions: At some point, the linker needs to assume that no global imports A and B exist, and any file exporting the
symbol NOT_A or NOT_B needs to be imported. However, the file which exported NOT_B may actually create a global import A after the file exporting NOT_A has
been imported. The linker does not detect this, so you need to be careful not to create such situations. They are especially difficult to detect if a lot of
combinations of AND and NOT operators are used, and if a lot of files that react to global imports create imports of their own.
In addition to user-defined global imports, the TIGCC linker also defines some global imports of its own, whenever special code is needed to handle a situation:
__kernel_program_header
This global import is created automatically if the linker is operating in kernel mode, and if the file is not declared as a library (see the _library control
symbol).
__kernel_library_header
This global import is created automatically if the linker is operating in kernel mode, and if the file is declared as a library (see the _library control symbol).
__fargo_program_header
This global import is created automatically if the linker is operating in Fargo II mode, and if the file is not declared as a library (see the _library control
symbol).
__fargo_library_header
This global import is created automatically if the linker is operating in Fargo II mode, and if the file is declared as a library (see the _library control
symbol).
__flash_os_header
This global import is created automatically if the linker is operating in Flash OS mode.
__nostub_comment_header
This global import is created automatically if NoStub data (comment) exports are defined for the program. The file reacting to this import must use
__ld_nostub_comment_count and __ld_insert_nostub_comments to insert the actual data exports into the header.
__handle_constructors
This global import is created automatically if constructors are defined for the program. The file which handles this import must query the constructor
section using the __ld_constructors_start, __ld_constructors_end, __ld_constructors_size, and __ld_constructor_count symbols.
__handle_destructors
This global import is created automatically if destructors are defined for the program. The file which handles this import must query the destructor section
using the __ld_destructors_start, __ld_destructors_end, __ld_destructors_size, and __ld_destructor_count symbols.
__handle_bss
This global import is created automatically if the program contains a BSS section (a section containing uninitialized global variables). No file needs to react
to this import; if the BSS section is not created at run time (using __ld_bss_size, __ld_bss_ref_count, and an appropriate insertion for the relocation), it
is simply passed on to the output file. If the output format does not support sections, the BSS section is merged with the other sections. However, if the
program reacts to this import, it absolutely must handle the relocation entries pointing into the BSS section.
__initialize_bss
This global import is created automatically if the program contains a BSS section, and the program requires the contents of this section to be initialized to
zero. The file reacting to this import must use __ld_bss_start, __ld_bss_end, and __ld_bss_size to query the location and size of the BSS section.
__handle_relocs
This global import is created automatically if the program contains absolute relocation entries. If no file reacts to this import, relocation entries have to be
handled by the output format. The file reacting to this import must use __ld_reloc_count and an appropriate insertion to get information about the
necessary relocation.
__handle_rom_calls
This global import is created automatically if the program contains ROM calls. If no file reacts to this import, ROM calls are handled by the output format.
The file reacting to this import must use __ld_rom_call_count and an appropriate insertion to get information about the ROM calls.
__handle_ram_calls
This global import is created automatically if the program contains RAM calls. If no file reacts to this import, RAM calls are handled by the output format.
The file reacting to this import must use __ld_ram_call_count and an appropriate insertion to get information about the RAM calls.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 152 of 173
__handle_libraries
This global import is created automatically if the program references at least one library. If no file reacts to this import, library calls are handled by the
output format. The file reacting to this import must use __ld_lib_count and an appropriate insertion to get information about the libraries.
__handle_data_var
This global import is created automatically if the data section of the program is not included in the program itself but in an external file. The file that
handles this import must open this file and relocate the program accordingly. It must refer to __ld_data_var_name_end, __ld_data_size, and an
appropriate insertion for the relocation.
__data_var_create_copy
This global import is created automatically if the data section of the program is not included in the program itself but in an external file, and this file needs
to be copied into memory (either always or under certain circumstances).
__data_var_copy_if_archived
This global import is created automatically if the data section of the program is not included in the program itself but in an external file, and this file needs
to be copied into memory only if it is archived. This import is created only in combination with __data_var_create_copy.
The TIGCC linker is capable of resolving references to certain built-in symbols. These symbols act just like normal externally defined symbols; for example, it is
possible to specify an offset to be added to the symbol in the reference. The symbols may resolve to numbers or addresses. The kind of symbol should be
obvious for each individual symbol; for example, it does not make sense to jump to __ld_bss_size because it resolves to a number. All numbers have to be
used as immediate values; if a symbol resolves to a number, treating it as an address and reading the value at this address will return garbage.
The following symbol names are treated as built-in symbol names, and resolved in a special way:
_ROM_CALL_...
tiamsapi_...
_RAM_CALL_...
_extraramaddr@..., _extraramaddr__...
...@????, ...__????
__ld_calc_const_...
__ld_entry_point
__ld_entry_point_plus_0x8000
__ld_program_size
__ld_constructors_start
__ld_constructors_end
__ld_constructors_size
__ld_constructor_count
__ld_destructors_start
__ld_destructors_end
__ld_destructors_size
__ld_destructor_count
__ld_reloc_count
__ld_data_start
__ld_data_end
__ld_data_size
__ld_data_ref_count
__ld_bss_start
__ld_bss_end
__ld_bss_size
__ld_bss_ref_count
__ld_rom_call_count
__ld_ram_call_count
__ld_lib_count
__ld_referenced_lib_count
__ld_export_count
__ld_nostub_comment_count
__ld_has_...
__ld_file_version
__ld_kernel_flags
__ld_kernel_bss_table
__ld_kernel_export_table
__ld_data_var_name_end
__ld_hardware_id
_exit
_comment
_extraram
_library
_ROM_CALL_...
The symbol _ROM_CALL_index is resolved to the ROM call with the index index, interpreted as a hexadecimal value. The operating system translates references
to such symbols in a way that they point to the specified ROM call. This is usually a function, but it can also be a variable.
tiamsapi_...
The symbol tiamsapi_index is resolved to the ROM call with the index index, interpreted as a decimal value. The operating system translates references to such
symbols in a way that they point to the specified ROM call. This is usually a function, but it can also be a variable.
_RAM_CALL_...
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 153 of 173
The symbol _RAM_CALL_index is resolved to the RAM call with the index index, interpreted as a hexadecimal value. If RAM calls are supported, the operating
system translates references to such symbols in a way that they either point to a specific location in memory, or are replaced by a specific value.
_extraramaddr@..., _extraramaddr__...
_extraramaddr@index and _extraramaddr__index are treated as references to an extra RAM address with the index index interpreted as a hexadecimal value.
index is an index into the extra RAM table defined by the program (using the _extraram symbol). The value which __extraramaddr... symbols are resolved to is
either the TI-89 or the TI-92(+)/V200 value of the table row specified by index.
Internally, extra RAM addresses are stored as RAM calls and treated the same way. __ld_insert_kernel_ram_calls and __ld_insert_preos_compressed_tables
output RAM calls and extra RAM addresses similarly to each other.
...@????, ...__????
The symbol libname@index or libname__index is resolved to a call to the library libname with the index index, interpreted as a hexadecimal value. index must
have exactly four hexadecimal digits; otherwise it will not be recognized. If library calls are supported, the operating system loads the specified libraries and
translates references to such symbols in a way that they point to the appropriate exported symbol in the library.
Library symbols are exported in the same way they are imported, except that the first part of the symbol (the library name) is not checked. If an exported
symbol in an object file has the form libname@index or libname__index, where index is a four-digit hexadecimal number and libname does not start with a dot
or an underscore, it is automatically exported from the program or library. The reason for this somewhat ambiguous pattern is purely traditional.
__ld_calc_const_...
__ld_calc_const_constants, where constants is an underscore-separated list of positive integer values in decimal or hexadecimal notation (prefixed with 0x),
resolves to one of the values in constants. The actual value depends on the calculator belonging to the file that is generated. This feature adds the possibility to
compile a program for multiple calculators at once and still generate different files for each calculator.
1. TI-92
2. TI-89
3. TI-92 Plus
4. V200
Values for calculators which the linker is currently not generating any output file for may be omitted. If a significant value is omitted, the value is assumed to be
zero, and a warning is emitted.
__ld_entry_point
References to this symbol are resolved to the first address of the program that contains executable code. If startup sections are defined, this is the address of
the first startup section. However, the exact meaning of the symbol is defined by the mode the linker is operating in, since startup sections do not necessarily
need to contain code, and an "entry point" in the sense of this symbol does not exist in all types of files.
Note: In Fargo II mode, all references to this symbol are manually shifted by two bytes in the negative direction, since Fargo heavily uses the program
variable's address as a base address, instead of the address of the Fargo header.
__ld_entry_point_plus_0x8000
__ld_program_size
This built-in symbol represents the size of the main section after all sections are merged into one. If all sections are merged into a single section, this is the size
of the final linked program (without any headers or footers required by the output format). If an external data variable is used, this would be the size of the
main executable only (but see the note about automatic insertion below).
Resolving of this symbol is delayed until the last pass of the linker in order to ensure the size isn't changed by later range-cutting. Currently, this is the same
pass which also does automatic insertions, so insertions may or may not be counted.
This symbol is currently used by the Flash OS support to write the OS size into the header which is sent to the calculator. Flash operating systems do not use
relocation, so the lack of support for automatic insertions is not a problem in this context.
__ld_constructors_start
This built-in symbol represents the beginning of the constructor section of the program. A constructor section contains an array of pointers to functions, all of
which do not take any parameters. These functions are to be executed at program startup. If no constructors are used, an error is reported.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 154 of 173
__ld_constructors_end
This built-in symbol represents the end of the constructor section of the program. A constructor section contains an array of pointers to functions, all of which
do not take any parameters. These functions are to be executed at program startup. If no constructors are used, an error is reported.
__ld_constructors_size
This built-in symbol represents the size of the constructor section of the program. A constructor section contains an array of pointers to functions, all of which
do not take any parameters. If no constructors are used, the symbol resolves to a value of 0. The value equals the value of __ld_constructor_count multiplied
by the size of a pointer, which is 4.
__ld_constructor_count
This built-in symbol represents the number of constructors the program uses. If no constructors are used, it resolves to a value of 0. The value equals the value
of __ld_constructors_size divided by the size of a pointer, which is 4.
__ld_destructors_start
This built-in symbol represents the beginning of the destructor section of the program. A destructor section contains an array of pointers to functions, all of
which do not take any parameters. These functions are to be executed at program startup. If no destructors are used, an error is reported.
__ld_destructors_end
This built-in symbol represents the end of the destructor section of the program. A destructor section contains an array of pointers to functions, all of which do
not take any parameters. These functions are to be executed at program exit. If no destructors are used, an error is reported.
__ld_destructors_size
This built-in symbol represents the size of the destructor section of the program. A destructor section contains an array of pointers to functions, all of which do
not take any parameters. If no destructors are used, the symbol resolves to a value of 0. The value equals the value of __ld_destructor_count multiplied by the
size of a pointer, which is 4.
__ld_destructor_count
This built-in symbol represents the number of destructors the program uses. If no destructors are used, it resolves to a value of 0. The value equals the value
of __ld_destructors_size divided by the size of a pointer, which is 4.
__ld_reloc_count
This built-in symbol resolves to the number of absolute relocation entries in this program/library, except relocation entries to sections which are handled
separately. If the program contains an external BSS and/or data section, relocs to this section are not counted, since they cannot be handled in the same
manner as relocs into the program code.
__ld_data_start
This built-in symbol represents the starting address of the data section, if the program does not mix text and data (for example if the data is written into an
external file). It points to the location behind the last item in the section. If the program does not contain an explicit data section, an error is reported.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 155 of 173
__ld_data_end
This built-in symbol represents the end of the data section, if the program does not mix text and data (for example if the data is written into an external file). It
points to the location behind the last item in the section. If the program does not contain an explicit data section, an error is reported.
__ld_data_size
This built-in symbol represents the size of the data section in bytes, if the program does not mix text and data (for example if the data is written into an
external file). If the program does not contain a data section, the symbol resolves to the value 0.
__ld_data_ref_count
This built-in symbol represents the number of references to the data section, if the program does not mix text and data (for example if the data is written into
an external file). If the program does not contain an explicit data section, it resolves to the value 0. If the data section is merged with the other sections, the
references counted by this symbol and the references counted by __ld_reloc_count will overlap.
__ld_bss_start
This built-in symbol represents the starting address of the BSS section. If the program does not contain a BSS section, an error is reported.
__ld_bss_end
This built-in symbol represents the end of the BSS section. It points to the location behind the last item in the section. If the program does not contain a BSS
section, an error is reported.
__ld_bss_size
This built-in symbol represents the size of the BSS section in bytes. If the program does not contain a BSS section, the symbol resolves to the value 0.
__ld_bss_ref_count
This built-in symbol represents the number of references to the BSS section. If the program does not contain a BSS section, it resolves to a value of 0. If the
BSS section is merged with the other sections, the references counted by this symbol and the references counted by __ld_reloc_count will overlap.
__ld_rom_call_count
This built-in symbol resolves to the number of ROM calls in this program/library. If the program/library does not reference any ROM code exports, it resolves to
a value of 0.
__ld_ram_call_count
This built-in symbol resolves to the number of RAM calls in this program/library. If the program/library does not reference any RAM exports, it resolves to a
value of 0. Extra RAM address references count as RAM calls as well. Note that RAM calls are handled purely by kernels, i.e. by middleware residing in the RAM.
__ld_lib_count
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 156 of 173
This built-in symbol resolves to the number of libraries needed by this program/library. The libraries do not actually need to be used; it is enough for a file to
specify a required minimum version for a specific library (see Minimum Library Versions). The idea is that a program should be able to specify a minimum
version for a library even if the library is only referenced indirectly via another one. See __ld_referenced_lib_count for a way to count only the libraries that are
actually used.
__ld_referenced_lib_count
This built-in symbol acts like __ld_lib_count, except that it counts only the libraries that are actually used. If the program only specified a minimum version for
a library, but did not use any of its exported symbols, this library is not counted.
__ld_export_count
This built-in symbol resolves to the number of exported items in the current program/library. This equals the highest export number present in the linked files
(see Library Calls) plus 1. For example, defining a single exported entry named mylib@00FF causes the export table to be 0x100 functions long, and therefore
this symbol to be resolved to a value of 0x100.
__ld_nostub_comment_count
This built-in symbol resolves to the number of NoStub data exports in the current program. Unlike for library exports, skipped indices are not counted.
__ld_has_...
The symbol __ld_has_items resolves to a nonzero value if __ld_item_count is greater than zero. Currently this value is -1, but do not rely on this!
__ld_file_version
This symbol resolves to the version number of the current program, defined with _version.... If no version number has been defined, it resolves to a value of 0.
__ld_kernel_flags
This symbol resolves to the value of the kernel flags. Kernel flags may be specified with _flag_... and with calculator control symbols.
__ld_kernel_bss_table
Usually, this symbol is simply resolved to a user-defined symbol named __kernel_bss_table. However, if the program does not contain a BSS section, it is
redirected to the entry point of the program. The effect is that constructs of the form
.word __ld_kernel_bss_table-entry_point
Note: If a program/library defines __kernel_bss_table, it absolutely must handle the BSS section. See __ld_insert_kernel_bss_refs for a way to get
information about references into the BSS section.
__ld_kernel_export_table
Usually, this symbol is simply resolved to a user-defined symbol named __kernel_export_table. However, if the program does not contain any exported
symbols, it is redirected to the entry point of the program. The effect is that constructs of the form
.word __ld_kernel_export_table-entry_point
__ld_data_var_name_end
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 157 of 173
This symbol is resolved to the address of the user-defined symbol __data_var_name_start, plus the length in bytes of the data variable name, plus 1 for the
zero byte at the beginning. If no data variable is specified for the program, an error is reported. The symbol __data_var_name_start must be defined and
exported by the program.
__ld_hardware_id
This built-in symbol resolves to the hardware ID of the target calculator type, a number used in the Flash OS stub.
_exit
Usually, this symbol is not handled in a special way. However, if it does not exist at all, it is redirected to the entry point of the program. The effect is that
constructs of the form
.word _exit-entry_point
The kernel headers of the standard library reference this symbol as the program/library destructor. For kernel programs and libraries, it is called whenever the
program exits or the library is unloaded.
_comment
Usually, this symbol is not handled in a special way. However, if it does not exist at all, it is redirected to the entry point of the program. The effect is that
constructs of the form
.word _comment-entry_point
The kernel headers reference this symbol as the comment string of the program. If it exists, it must be a zero-terminated ASCII string.
_extraram
Usually, this symbol is not handled in a special way. However, if it does not exist at all, it is redirected to the entry point of the program. The effect is that
constructs of the form
.word _extraram-entry_point
The kernel headers of the standard library reference this symbol as an extra RAM table. The table is organized in pairs of 16 bit values. Of each pair, the first
value is relevant for the TI-89, and the second value is relevant for the TI-92(+)/V200 calculator family. In C, you would define an extra RAM table like this:
struct {
short value89, value9x;
} _extraram[] = {{v1_89, v1_9x}, {v2_89, v2_9x}, ...};
However, extra RAM tables are barely usable in C: The compiler does not support using external symbols as immediate values, except if you take their address.
_library
Usually, this symbol is not handled in a special way. However, if it does not exist at all, it is redirected to the entry point of the program. The effect is that
constructs of the form
.word _library-entry_point
Note: _library is also a control symbol, which means that under normal circumstances, references to it are not allowed. However, in Fargo II mode, programs
and libraries have special permission to use this symbol.
The TIGCC linker can insert certain variable-length data into the contents of sections. If a symbol (i.e., a label) at the end of a section is recognized as an
insertion point, then the linker appends the data specified by the symbol name. If the symbol is not at the end of a section, the insertion will fail without notice,
since these contents may have been inserted automatically already.
You may refer to an insertion symbol even if you did not put a label at a specific place. In this case, the data is written to an arbitrary place (usually the end of
the program, but do not rely on this). However, all object files and archives are searched for exported symbols with this name first, to avoid duplication of the
data.
This method is only used if some program-related data cannot be expressed using simple built-in symbols. It should be used with care, as the inserted data
may be invalid under certain circumstances. The format of the data is fixed and usually represents some already established data format, but new data formats
may be developed on demand. The insertion symbols which are currently recognized are:
__ld_insert_kernel_relocs
__ld_insert_compressed_relocs
__ld_insert_fargo021_relocs
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 158 of 173
__ld_insert_kernel_bss_refs
__ld_insert_compressed_bss_refs
__ld_insert_fargo020_bss_refs
__ld_insert_fargo021_bss_refs
__ld_insert_kernel_data_refs
__ld_insert_compressed_data_refs
__ld_insert_kernel_rom_calls
__ld_insert_compressed_rom_calls
__ld_insert_kernel_ram_calls
__ld_insert_kernel_libs
__ld_insert_fargo020_libs
__ld_insert_fargo021_libs
__ld_insert_kernel_exports
__ld_insert_fargo_exports
__ld_insert_preos_compressed_tables
__ld_insert_nostub_comments
__ld_insert_data_var_name
__ld_insert_kernel_relocs
Relocation entries indicate that the program needs to know some addresses which are only available at run time. In this case, the addresses referred to are
locations inside the program code or data. Usually, all references to absolute addresses inside the program are inserted into the section if one of these two
insertions is used; however, sections may be marked as being handled in another way, which prevents relocation entries to them from being output in this way.
The data section is automatically marked as handled if it is externalized; the BSS section is marked as handled by referencing __ld_kernel_bss_table, by using
__ld_insert_kernel_bss_refs before inserting the relocation entries, or by reacting to the __handle_bss global import.
__ld_insert_kernel_relocs uses the kernel format for storing relocation entries, which is used by kernels on the TI-89, TI-92 Plus, and V200, and by Fargo
v0.2.0:
Before program termination, this process has to be reverted, so that it can be repeated the next time the program starts. Since programs may be moved in
memory while they are not executed, they may not simply deactivate the relocation code. This would also prevent programs from being transferred between
devices.
Note: Relocation entries may only be inserted at a single place in the program. The reason for this is that the linker may have to add new relocation entries
after they have been written into the section. Instead of keeping track of which entries have already been processed, we thought it would be easier to remove
them once they have been written into a section. Also, it is dangerous to use this insertion from anything other than a startup section.
__ld_insert_compressed_relocs
__ld_insert_compressed_relocs inserts relocs in a compressed format known from Fargo. For more information on inserting and processing relocs, see
__ld_insert_kernel_relocs.
In the following format description, offset refers to the difference in words (half of the difference in bytes) between the start of this reloc and the end of the
previous reloc. If there is no previous reloc (i.e. for the first reloc), offset is the distance in words between this reloc and the symbol
__ld_compressed_relocs_ref. This symbol must be exported to be found. If it is not found, the entry point is used instead (see __ld_entry_point).
__ld_insert_fargo021_relocs
__ld_insert_fargo021_relocs inserts relocs in the compressed format used by Fargo 0.2.1. For more information on inserting and processing relocs, see
__ld_insert_kernel_relocs.
This insertion is the same as __ld_insert_compressed_relocs, except that the the reference symbol used if there is no previous reloc (i.e. for the first reloc) is
__ld_fargo021_relocs_ref. It is expected by Fargo to be at a fixed position: the position of the format flag in the Fargo header. This is currently handled by
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 159 of 173
__ld_insert_kernel_bss_refs
__ld_insert_kernel_bss_refs outputs references to the BSS section in the format defined in __ld_insert_kernel_relocs. The only difference is that the relocation
address is not the entry point of the program but the beginning of the BSS section.
If you insert these references, the linker assumes that the BSS section is handled by you; that is, you have to allocate it dynamically using __ld_bss_size and
use a pointer to it as the relocation address.
__ld_insert_compressed_bss_refs
__ld_insert_compressed_bss_refs inserts relocs in the format defined in __ld_insert_compressed_relocs. The only differences are that the relocation address is
not the entry point of the program but the beginning of the BSS section and that the reference symbol used if there is no previous reloc (i.e. for the first reloc)
is __ld_compressed_bss_refs_ref.
If you insert these references, the linker assumes that the BSS section is handled by you; that is, you have to allocate it dynamically using __ld_bss_size and
use a pointer to it as the relocation address.
__ld_insert_fargo020_bss_refs
__ld_insert_fargo020_bss_refs acts like __ld_insert_kernel_bss_refs, except that it always outputs the two terminating zero bytes, even if no references into
the BSS section exist.
__ld_insert_fargo021_bss_refs
__ld_insert_fargo021_bss_refs inserts relocs in the compressed format used by Fargo 0.2.1. It acts like __ld_insert_compressed_bss_refs, except that the size
of the BSS section is automatically output (as a 2-byte entry) in front of the actual relocation table, and that the reference symbol used if there is no previous
reloc (i.e. for the first reloc) is __ld_fargo021_bss_refs_ref. It is expected by Fargo to be at a fixed position: the position of the format flag in the Fargo
header. This is currently handled by the definition of the Fargo header.
__ld_insert_kernel_data_refs
__ld_insert_kernel_data_refs outputs references to the data section in the format defined in __ld_insert_kernel_relocs. The only difference is that the relocation
address is not the entry point of the program but the beginning of the data section.
If you read the data from an external variable (see __handle_data_var), you have to use the address of the variable (or a copy) as the relocation address.
__ld_insert_compressed_data_refs
__ld_insert_compressed_data_refs outputs references to the data section in the format defined in __ld_insert_compressed_relocs. The only differences are that
the relocation address is not the entry point of the program but the beginning of the data section and that the reference symbol used if there is no previous
reloc (i.e. for the first reloc) is __ld_compressed_data_refs_ref.
If you read the data from an external variable (see __handle_data_var), you have to use the address of the variable (or a copy) as the relocation address.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 160 of 173
__ld_insert_kernel_rom_calls
__ld_insert_kernel_rom_calls can be used to handle ROM calls. It inserts references to ROM calls in the format used by kernels:
Before program termination, this process has to be reverted, so that it can be repeated the next time the program starts. Simply deactivating the relocation
code would prevent programs from being transferred between devices.
__ld_insert_compressed_rom_calls
__ld_insert_compressed_rom_calls can be used to handle ROM calls. It inserts references to ROM calls in a compressed format known from Fargo but
specifically altered for TIGCC:
__ld_insert_kernel_ram_calls
__ld_insert_kernel_ram_calls can be used to handle RAM calls. It inserts references to RAM calls in the format used by kernels:
Before program termination, this process has to be reverted, so that it can be repeated the next time the program starts. Simply deactivating the relocation
code would prevent programs from being transferred between devices.
__ld_insert_kernel_libs
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 161 of 173
__ld_insert_kernel_libs can be used to handle library calls. It inserts references to libraries in the format used by kernels:
Before program termination, this process has to be reverted, so that it can be repeated the next time the program starts. Since programs and libraries may be
moved in memory while they are not executed, they may not simply deactivate the relocation code. This would also prevent programs from being transferred
between devices.
__ld_insert_fargo020_libs
__ld_insert_fargo020_libs can be used to handle library calls. It inserts references to libraries in the format used by Fargo v0.2.0:
The libraries have to be processed using the method described in __ld_insert_kernel_libs, except that library versions are not implemented by this format.
__ld_insert_fargo021_libs
__ld_insert_fargo021_libs can be used to handle library calls. It inserts references to libraries in the format used by Fargo v0.2.1:
The libraries have to be processed using the method described in __ld_insert_kernel_libs, except that library versions are not implemented by this format.
__ld_insert_kernel_exports
__ld_insert_kernel_exports can be used to export symbols from a library. It treats all symbols that are declared external and look like "libname@index" or
"libname__index" as exported entries. index is a hexadecimal number which must have exactly 4 digits.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 162 of 173
2 bytes: location (offset from the beginning of the library; may be 0 if nothing was specified)
2 bytes: 0
Note: Since exported entries are stored one after another, skipped entries will take up additional space in the export table. For example, if you only define one
symbol called "libname@0010", then there will be 16*2=32 bytes of zeroes in the export table.
__ld_insert_fargo_exports
__ld_insert_fargo_exports can be used to export symbols from a library. It treats all symbols that are declared external and look like "libname@index" or
"libname__index" as exported entries. index is a hexadecimal number which must have exactly 4 digits.
__ld_insert_fargo_exports inserts library exports in the format used by the Fargo II kernel:
Note: Since exported entries are stored one after another, skipped entries will take up additional space in the export table. For example, if you only define one
symbol called "libname@0010", then there will be 16*2=32 bytes of zeroes in the export table.
__ld_insert_preos_compressed_tables
__ld_insert_preos_compressed_tables is the most complex of the automatic insertions. It inserts all relocation-related tables in the compressed format
expected by PreOs 0.68 or higher. PreOs expects those tables to be pointed to by the same pointer, so they need to be inserted all at once. The reference
address expected by PreOs is the same for all relocation tables: 36 (0x24). It is defined as the end address of the smallest possible header/stub combination.
(However, the smallest possible stub is not usable in practice because it does not emit any error messages. Therefore, the address does not correspond to any
actual address in TIGCCLIB, so it is hard-coded in the linker.) The tables it inserts are, in order:
PreOs uses a special format for the indices. It is not the same as for the relocation table. Instead, a PreOs index is encoded using one of the following formats:
where index is the actual index, and offset is index + 1 for the first index and the difference between index and the previous index for the following ones.
Note: Since parts of this insertion are dealing with relocs, the limitations of __ld_insert_kernel_relocs also apply to this insertion.
__ld_insert_nostub_comments
__ld_insert_nostub_comments is used to export data symbols in the NoStub comment header. It treats all symbols that are declared external and look like
"_nostub_data__index" as exported entries. index is a hexadecimal number which must have exactly 4 digits.
__ld_insert_nostub_comments inserts data exports in the format used by the NoStub comment specification:
__ld_insert_data_var_name
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 163 of 173
__ld_insert_data_var_name inserts an ANSI string containing the name of the data variable as specified during the invocation of the linker. A terminating zero
byte is appended; however, the name does not automatically start with a zero byte.
The TIGCC linker can do many operations on binary code. If you want it to behave correctly in all cases, you need to make sure that no executable code is
included in a data section, and no data is included in a code section. However, TIGCC usually merges all data into the code section to optimize references to it,
so in rare cases it is possible for the linker to generate incorrect code.
The TIGCC linker features the removal of unnecessary NOP instructions. For file formats which may insert a NOP (No OPeration) instruction at the end of a
section in order to align its size to a specific boundary, it can remove this instruction to save a little space. Currently only the AmigaOS format is known to do
this (see TIGCC Linker File Formats). If the section ends with more than one NOP instruction, all instructions are kept.
The TIGCC linker can optimize function return sequences. If a section ends with a subroutine branch followed by a simple return instruction, the subroutine
branch is converted into a simple unconditional branch (jump), and the return instruction is removed. Note that this may fail easily if there is a branch to the
return instruction somewhere; if the return instruction is removed, the branch will point to arbitrary code or data. You can make this less likely by telling the
assembler to emit all local labels, so the linker knows it cannot optimize a return sequence because there is a label in front of the return instruction. With the
GNU Assembler, this is done by using the '--keep-locals' option, which is included automatically if range-cutting is enabled. With the A68k Assembler, the '-d'
switch does the job.
On some architectures, certain branches are not permitted. For example, on the MC68000 processor, it is not possible to branch to the next instruction using a
short branch. While the assembler usually detects such invalid situations, they may still occur if the branch target is in a different section or file. The TIGCC
linker detects such invalid situations and tries to resolve them as well as possible: If it is invalid for a branch at the end of a section to point to the beginning of
the next section, it is removed unless it is a subroutine branch. For subroutine branches, a NOP instruction is inserted instead.
In addition to fixing invalid branches, the TIGCC linker can optimize branch instructions to reduce the number of absolute relocations needed. If an absolute
branch (jump or subroutine branch) can be converted to a relative branch, the operating system does not need to insert the destination address at run time;
therefore this will save space. Moreover, if range-cutting is enabled, optimizing branches can reduce the size of the code.
The linker can convert absolute branches (which would normally need a relocation entry) into special relative F-Line sequences. These sequences are handled
by an interrupt handler. The fact that an interrupt is needed makes these branches significantly slower, but using them can save quite a bit of space in the
program.
There are two types of F-Line branches: The default version can be activated using the __ld_use_fline_jumps control symbol. Each branch has a size of six
bytes. They are relative to their own address, which means that they can be supported by the AMS, and in fact, the AMS implements an interrupt handler for
these branches starting from version 2.04. The other version can be activated using the __ld_use_4byte_fline_jumps control symbol. As the name says, each
branch has a size of four bytes. They are relative to the program's entry point, so only an emulator that is installed from the program can handle them. Since
they use codes that are otherwise used for ROM calls, this might break applications that are called from the program, if any. However, this is very unlikely, as
the two ROM calls used are not defined yet.
If this type of optimization is turned on, then the TIGCC linker optimizes all instructions that move data between two places. This includes instructions to move
data between memory and registers or between two places in memory, instructions to load the address a of memory location into a register, and instructions to
push the contents of a memory location on the stack. Note that due to the great variety of such instructions, this optimization is more likely to cause errors
than others.
This optimization can reduce the number of absolute references to locations inside the program, and it can also decrease the size of the code if range-cutting is
enabled.
If this type of optimization is turned on, then the TIGCC linker optimizes all instructions that compare the contents of a memory location with something. This
includes operations that compare data and operations that test whether something is zero.
This optimization can reduce the number of absolute references to locations inside the program, and it can also decrease the size of the code if range-cutting is
enabled.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 164 of 173
If this type of optimization is turned on, then the TIGCC linker optimizes all instructions that perform calculations based on data stored in memory. This includes
addition, subtraction, multiplication, division, and bitwise manipulation instructions.
This optimization can reduce the number of absolute references to locations inside the program, and it can also decrease the size of the code if range-cutting is
enabled.
If you turn on dumps in ld-tigcc (using the '--dump[n]' option), ld-tigcc prints the contents of the internal data structures to standard output between
various events during the linking stage. These places are numbered, so that you can turn on a specific dump by adding an index to the option. The following
table shows the current location of the different dumps:
Dump 0
This dump is produced just after all object files have been imported. Relocation entries that refer to different files have not been resolved yet; neither
have ROM/RAM/library call symbols been translated into actual ROM/RAM/library calls. Archive members have only been imported if this was specified by
a global import.
Dump 1
Relocation entries have been resolved to the maximum extent possible. If they could not be resolved to existing symbols or had been treated as
RAM/ROM/library calls, archive members have been imported for them.
Dump 2
All uninitialized and zero-data sections have been merged, as well as all data sections if this was necessary. Automatic global imports have been added.
Dump 3
All global imports have been processed; even the ones which contained negations.
Dump 4
Relocation entries from the archive members which were just imported by global imports have been resolved, possibly importing new archive members. If
relocation optimization is enabled, another dump is appended with the same contents after relocation optimization. If removal of unused sections is
enabled, a third dump is inserted after this removal.
Dump 5
All sections which are not externalized have been merged. Note that some parts of the code fixup need to be done just before the sections are merged, so
there is also a lot of code fixup and optimization between dumps 4 and 5.
Dump 6
The remaining code fixup and optimization has been performed.
Dump 7
Certain built-in symbols whose value depends on the program contents have been resolved. Insertions that were requested to be added at an arbitrary
place have been added to the end of the program.
Dump 8
Relative relocation entries have been replaced by the actual distances they had represented.
The program dumps are usually self-explaining; however, a few items require special attention:
address: (!)
Indicates an internal inconsistency (for example an item outside of a section, overlapping items, or an internal ordering error).
Section offsets and data are always output in hexadecimal notation. Question marks indicate uninitialized data, which may have random content.
Recompiling ld-tigcc and ar-tigcc (or the corresponding link DLL) from source may be useful if you want to make the linker as efficient as possible by
disabling certain features. Recompilation requires GCC and GNU make. If you are using Linux, you may simply run make in the source code directory; the same
is probably true for other Unix variants. If you are using Windows, you need to download MSYS or make some minor modifications to the makefile.
If you only want to disable some features, you can take a look at the definitions in the makefile (the file called Makefile). The DEFINES variable contains the
general features to be included; EXE_DEFINES contains the features that should only be included in the executable files (not in the DLL). All available definitions
are documented at the top of generic.h.
For example, if you want to disable support for the AmigaOS files generated by the A68k Assembler, you may simply remove the '-DAMIGAOS_SUPPORT'
definition from the DEFINES variable. Note that some combinations are invalid; for example, if you disable support for all object file formats, you will get a "file
format not recognized" error whenever you try to link some files.
The TIGCC IDE is a freely distributable Integrated Environment for TIGCC, written by Sebastian Reichelt. It is very easy to use, even for unexperienced
programmers. This part of the documentation was written by Sebastian.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 165 of 173
Note: If you want to use the command-line compiler to compile .tpr files produced by the IDE, you can use the tprbuilder utility. It takes the name of
a .tpr file as a single parameter. You may have to tweak your source files a little, as the IDE uses a different compilation scheme.
Click on 'File/Preferences'. In the 'Preferences' dialog box, you can customize the IDE with various options. Some options are very important, others are simply
user interface settings.
If you want to be able to cancel compiling operations more quickly, you can choose to force-quit the application used for the process. This is not recommended,
however, and can make your system unstable. If you do not choose this option, the IDE compilation window remains on the screen until process is finished. If
you click on 'Stop' again, the process will finally be terminated. If you choose this option, you should also activate the 'Auto-Save' option.
If you want to be able to react to compilation errors more quickly, you can choose to stop compilation when the first file was not compiled successfully.
Otherwise, the IDE compiles all files, displaying all errors in the error list.
When a program is compiled, usually assembly as well as object files are produced and stored in the project folder. You can have them deleted automatically
after the program was linked successfully.
There is one extremely important option: the automatic splitting of source files into more lines. This is done in order to accurately find the position of errors in
your code. It might, however, result in an error being reported when there is nothing wrong with the code. This is unlikely, though, since this option has been
tested very thoroughly.
Another important option is the Template Wizard. It helps you to get started with a project when you add your first file. If you disable it, default options will
automatically be used.
You can have the IDE automatically check the Official TIGCC Site for new headlines on startup. This way you always know whether there are any updates, like
new beta versions to test.
To be able to run your program directly from the IDE, you need to specify either to run on VTI, or you need to select your link port and cable type. Do this in
the 'Transfer' tab. You can switch between the two very quickly by pressing Shift+Ctrl+Alt+F9.
In the 'Syntax Highlighting' tab, you can set your own settings for both ASM and C files. If syntax highlighting takes up too much time when opening a project,
you may want to disable it.
To customize syntax highlighting, you can specify your own colors and styles for different types of characters using the buttons provided. To set colors and
styles for comments, strings, and compiler directives, use the tree at the bottom of the dialog. To edit such a 'custom style', double-click on it. You can also
specify the exact beginning and end, using '#13' as substitute for the end of the line.
In this tree, you can also create your own custom set of words that are supposed to be highlighted some way. Only a list of reserved words is included by
default, but you can add lists of your own if you want to.
Click on 'File/New/Project'. If the project you had opened before has been modified, you are informed about it, and you have the choice to save your project
first.
When you create a new project, it is best to save it first in order to give it a file name. Click on 'File/Save Project As...' and save your project. Note that the
executable files (*.89z; *.9xz; *.v2z) are saved with the same name as your project file, even if it is a long file name. To specify the name your program gets
when it is transferred to the calculator, click on the top item in the project tree twice in a row in order to rename it (optionally including a folder name). Of
course, the same restrictions apply as to calculator variable names. For other options, look under 'Project/Options...', especially 'Program Options...' in the
'Compilation' tab.
After you did that, you need to create a new C file to start with. Click on 'File/New/C Source File'. A file template is displayed, where you can simply add your
code at the position where it says:
Click on 'Help/Index' for a complete documentation of functions supported by the TIGCC Library, and you can start programming.
To start a new Assembly project, you have to perform the same steps as for a C project; the only difference is that you have to click on 'New/GNU Assembly
Source File' or 'New/A68k Assembly Source File' instead. Note that you can also have a mixed project with both file types. Assembly projects are not supported
and tested as well as C projects.
To add an existing file, click on 'Project/Add Files...' and select the files you want to add. These can be C or Assembly source files, header files, or object files.
Generally you can include any file that belongs to your project, even text files, in order to edit them and to keep them together. Source files always have to be
added to the project in order to be found.
Header files can be either C or Assembly files. If you know enough about C, you can create C-style header files, create C source files implementing the functions
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 166 of 173
defined in the header files, and export functions from them. Note that you always have to add the header and either the source or object files if you want to use
them in another project. There is also a common include folder for general-purpose header files.
When you create a C-style header file, you can only include it in C source files. Similarly, if you create an Assembly-style header file, you can only use it in
Assembly source files.
For tab width and syntax highlighting, it is necessary that you indicate what type of header file you are creating by using a comment at the beginning. If you
enabled the Template Wizard, you can choose what type of header file you want to create.
Files included in A68k files with 'incbin' have to be in the 'other files' section.
To rename a source file, simply rename it in the project tree. To save it with a different name, click on it with your right mouse button, and select 'Save As...'
from the popup menu.
To save changes to a file, right-click on it and select 'Save'. You can also click on 'File/Save All' to save all files.
Editor Features
To print the current source file, click on 'Print...' from the menu or the toolbar. To find or replace text, use the 'Find' menu. There you will also find a menu item
to jump to a function in the editor. Note that this can be done much quicker using the toolbar.
If you want to open a source file whose name is in the current source code, move your cursor to the file name and press Ctrl+Enter. If the file is not included in
the project, it will be opened in a popup editor.
You can use Ctrl+Tab to switch between source files. Files in the project tree which are not visible at the moment are skipped.
Press Ctrl+Space to activate auto-completion for the current word. Press Ctrl+J to use a predefined template.
To compile and run your program, press F9, or select 'Run' from the 'Debug' menu. Like 'Project/Make', this will perform all the steps necessary to create the
executable file; then it will send the file to the device or program you specified in the preferences. If some files are not compiled, but they have been changed
or need to be recompiled for some reason, click on 'Project/Build'.
You can also choose only to compile all files without creating an executable file by clicking on 'Compile'. A 'Compile' item is also available for each source file in
the popup menu of the project tree.
If you need to change the link order of files, you can do this by dragging a file to another place in the same file group. You can use drag and drop also to move
files between categories.
In the project options, you can specify how your program is built. This also includes automatic compression. If you use this feature, two files will be compiled: a
small starter program and a compressed program file. The on-calc variable name that you specify cannot be the same as the on-calc variable name of your
program (which will be the name of the starter program in this case).
In the same dialog, you can also enter the starting parameters for your program. These parameters are pasted into the command line between the
parentheses.
If one or more errors were found when compiling, an 'Errors and Warnings' box is displayed at the bottom of the main window. If you click on an error, the IDE
jumps to the position in the source file where the error occured, if the position is available.
The compiler stops at errors, but not at warnings. To turn warnings off, use the switches available in 'Project/Options...'. Click here for details about switches
supported by the GCC compiler. Note: Not all of these switches can be used from the IDE.
If you are experienced in the use of VTI to track down runtime errors, the 'Debug Information' option may help you. If you set it, the generated .s file(s) will be
filled with lines from the source code, along with offsets from the first instruction of the program.
Special Features
Auto-Indenting:
If you press Enter in the editor, the cursor will be under the first non-whitespace character of the previous line.
Auto-Blocks:
If you press '{' on a new line, the corresponding '}' is created automatically, and all formatting with tabs is done automatically as well. You can disable
this feature.
Error Tracking:
Even if you edit a source file, clicking on an error will still jump to the correct position. Optionally, error list entries are deleted when you delete the
character that caused the error.
Keyword Search:
Pressing F1 on a TIGCC Library function or a keyword will search the index for that function.
Code Auto-Completion:
The editor implements several features to make writing code using the predefined library calls easier.
Planned Features
A debugger
A sprite editor producing C or ASM header files
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 167 of 173
Disclaimer
I cannot be held responsible for any error or system failure caused by this program or any programs related to it. Use this program at your own risk.
Feedback
Feel free to contact me if you have any questions, comments, or bug reports. If you found a bug, please don't just think I will probably find it, because I
probably won't. Instead, please use the bug report form at tigcc.ticalc.org immediately.
Version History
Replaced the title and wizard images and the icons by new ones created by Gereon Kindler.
Implemented storing file names in relation to the project directory.
Added optional drag and drop text editing.
Speeded up source file splitting.
Implemented a "Remove Trailing Spaces" feature.
Fixed the bug which would make closing large files really slow.
Implemented a Ctrl+Tab shortcut to switch between files.
Introduced special mouse wheel support for people with wheel problems.
Added the possibility to run a batch file after building.
Added a detection to warn if a file was modified on the disk.
Background compilation.
Support for linking multiple files through the GNU linker.
Support for creating and using archives.
Creation of debug information in the .s file.
Drag and drop support from the explorer.
Headline download (manually and automatically).
Send to calc/VTI support.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 168 of 173
Editor bugfixes.
Never officially released (beta) (too many missing features and bugs).
File date checking.
Assembler bug workaround.
Stable force-quit operation.
Toolbar, status bar, icons in menus.
More editor options.
Header file error display.
Initial release.
Included all three programs.
Fully functional IDE.
Extraction of errors from all three programs.
Almost 100% accurate error tracking.
Use of projects.
The TIOS has a very rich set of built-in functions, but unfortunately they are not yet documented by TI. However, entry points are documented. As nearly 80%
of functions which I defined in this library are just TIOS calls (either direct or indirect, depending of whether the compile mode is "Doors" or "nostub"), the
documentation of these functions are also the documentation of TIOS calls. This means that this document documents about 600 TIOS calls, so it may be very
valuable for assembly programers. When the function is nothing more than simple TIOS call, I give to it the name which is exactly the same as the name used
in TI list of TIOS entry points. So you can easily determine which functions are simple TIOS calls.
Of course, function parameters are listed using the C language calling convention, because this is a library for C programing. If you are an assembly
programmer, you need to know the following:
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 169 of 173
Although the "char" type occupies just one byte, it must be promoted to a word before pushing it on the stack.
To clean up after the function has been called, pop all the values that were pushed. This can be done by adding a value to SP; this value is calculated by
summing the sizes of all the parameters that were pushed.
Assume that D0-D2/A0-A1 are destroyed by any given ROM function upon return.
Any function which returns any non-pointer type (char, short, int, long), including not-too-long structures (like HSym), keeps the result in the register D0.
Any function which returns a pointer type keeps the result in the register A0.
All TIOS functions which return a floating point value (like most functions from timath.h header file) expect that before calling A6 points to the byte after
the end byte of 10-byte long buffer where the result will be stored (usually this is a preallocated space on the stack frame). Note that this is not the same
as GCC convention for returning floating point values: GCC returns floats in a triplet [D0.l;D1.l;D2.w]. That's why implementing floating point routines
was not so easy, especially because A6 is a very important register (used in GCC as the frame pointer).
Many users ask me for examples, especially about the usage of floating point functions in ASM programs. I expected that everything I wrote is so clear (for
anybody who knows C syntax), but it seems that it is not. OK. I will give two examples (the second one deals with floats):
Example 1:
Look at the DrawClipEllipse function from the graph.h header file. It is declared as
void DrawClipEllipse (short x, short y, short a, short b, const ScrRect *clip, short Attr);
in the ASM program, you should do the following code (Doors calling convention will be assumed, due to simplicity):
move.w #1,-(sp)
pea clip(pc)
move.w #20,-(sp) ; Using move.l #$1E0014,-(sp) you can pack
move.w #30,-(sp) ; these two ASM instructions into one
move.w #50,-(sp)
move.w #20,-(sp)
jsr tios::DrawClipEllipse
lea (sp,14),sp ; The same as add.l #14,sp but shorter
...
clip: dc.b 0,0,159,99 ; Components of SCR_RECT structure are bytes
Example 2:
This example will show to you how to use floats in ASM programs. Look at the functions log, fmul and trunc from the timath.h header file. They are declared as
Suppose that you want to calculate the integer part of 2.34*log(342.1178). First, you need to know that hexadecimal representations for 2.34 and 342.1178
are $40002340000000000000 and $40023421178000000000 (see bcd if you don't know why). Also, note that bcdmul and bcdlong are original TIOS names for
functions aliased as fmul and trunc (don't be misleaded by the fact that the library defines fmul & trunc to work with native float type and bcdmul & bcdlong to
work with bcd structures; at the fundamental ASM level they are exactly the same routines). Then, this calculation may be performed using the following ASM
program:
This program may be much more optimized if you know how to use stack frames properly (this technic is so popular in high-level language compilers, but quite
unpopular in ASM programs; this example shows that stack frames may be very useful). The optimized version of the same program follows:
Note: Some of the information about TIOS calls given by TI itself on their site is incomplete or even wrong. This document contains more precise information.
Contact Information
As I wrote this documentation, surely the most of all questions will be addressed to me. So, if you have any questions, suggestions, problems, corrections, bug
reports, and especially if you have some information about TIOS routines not known to me, please mail me at
Zeljko Juric
Sarajevo, Bosnia & Herzegovina
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 170 of 173
Please, inform me about any noticed problem with the library and the documentation (including wrong links in the documentation). This will help me to correct
the problem in a next release. However, please use the bug report form on tigcc.ticalc.org for all other problems.
If you have a general TIGCC programming question, it is a good idea to see whether it is already answered on the TIGCC programming message board. If
not, you can post your question there.
Note: Before asking me a question, please check whether this question is already answered in the Frequently Asked Question list: I am tired of answering
questions which are already answered there!
Copyright Notes
As TIGCC is a complex team project, various parts of it have been made by different authors:
Some parts of the TIGCC package (cpp, gcc, as, ld, ar, objcopy) are modified parts from the GNU Compiler Collection and GNU BinUtils packages. These parts
are free software; you can redistribute them and/or modify them under the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later version.
Parameter passing by register Copyright (C) 1998-2003 Fred Fish from Geek Gadgets; converted to GCC 3.0 by Kevin Kofler.
a68k (also included in the package) is a freeware assembler by Charlie Gibbs (it is a somewhat modified Amiga version).
Thomas Nussbaumer holds the copyright for the TIGCC Tools Suite, from which the compression feature was taken.
All information presented in the documentation are strictly mine, not by Texas Instruments (except information about GNU products, which are based on the
original GNU manuals). All of TIOS-specific information in this document are result of a hours of work with the debugger. But I need to give credits to Gareth
James: his informational files, although extremely briefly, help me a lot to understand some particular TIOS secrets.
The TIGCC library and documentation is absolutely free for any distribution if you don't change anything in this package. But, to give credit to my hard work,
please do the following:
If you use any routine from this library in your program, put this fact in the documentation of your program;
If you use a routine in your assembly program which usage wasn't known to you before reading this documentation, put this fact in the documentation of
your program.
I simply want that this documentation to become known to as many C and assembly programmers as possible.
Updated: Greatly changed the structure of the whole library, making it cleaner and easier to read.
Updated: Made some changes to support the new '-mregparm' switch/option.
Added: Implemented F-Line ROM Calls.
Added: Added beta version information to version.h.
Added: Implemented checking for a minimum AMS Version.
Added: Added types such as SYM_STR to differentiate between different uses of similar constructs.
Added: Added the ESTACK macro.
Added: Added a TRAP macro which acts like AUTO_INT.
Added: Added bitwise functions to peekpoke.h.
Added: Added a lot of new functions to unknown.h.
Added: Started documenting more functions from unknown.h, especially the high-level functions VarRecall and VarStore.
Updated: Made _rowread a library function.
Added: Added the _rowread_inverted, _rowread_internal, _keytest, and _keytest_optimized functions.
Added: Added missing interrupt vectors.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 171 of 173
Updated: Made some changes that will hopefully enable support for the new V200 calculator. You can define USE_V200 to activate this.
Added: A new file version.h has been added to the library.
Updated: Updated fopen and fclose with new versions by Greg Dietsche.
Bugfix: Implemented variable-type arguments for pointers to short and long integers. This prevents warnings if you pass an int pointer to a short pointer
argument, and fixes the problems introduced in release 2.31.
A standard library file has been added to work with multiple files.
New flickerless grayscale support implemented by Thomas Nussbaumer has been added.
GrayMode has been replaced by GrayOn and GrayOff.
Bugfix: Casting floats to integers and automatic trunctation floating point values now works correctly. In TIGCCLIB 2.3, casting to signed ints (including
implicite truncation) produced incorrect values, and casting to unsigned ints produced 'Undefined reference' errors. This is fixed now.
Bugfix: Many programs created with library releases prior to 2.3 produce a lot of warnings (although they work correctly after the compilation) about
incompatible pointer types. This is fixed now.
Bugfix: Functions OSContrastUp and OSContrastDn trashed some registers due to a bug in the TIOS. This is fixed now (thanks to Patrick Davidson).
Bugfix: Programs which still have directives USE_..._PATCH couldn't be compiled in "Doors" mode ('Duplicate identifier' errors) with TIGCCLIB 2.3, due to
superfluous declarations of some symbols (bcopy etc.) in doors.h header file. This is now fixed.
Functions abs, min and max are now redefined to work with any numeric type, not only with short integers. Such behaviour is proposed in ANSI C.
Indentifiers AUTO_INT, AUTO_INT_COUNT, FIRST_AUTO_INT and LAST_AUTO_INT were introduced in TIGCCLIB 2.3, but I forgot to document them. This
is now corrected.
As usual, there are some fixes in the documentation. Especially, thanks to Kevin Kofler for very important information about returning values to TI-Basic.
A lot of internal changes are made in the library to support new features introduced in release 0.9 of the compiler. That's why this release of the library
will not work correctly with releases of TIGCC prior to 0.9.
The timath.h header file is completely rewritten, because the compiler now supports the native ANSI C floating point types and values (click here for more
info). In addition to this, two new ANSI-compatible header files math.h and float.h are introduced too. These changes are performed on such way to
retain about 95% compatibility with old programs which used floating point arithmetic using awkward indirect methods (i.e. the only possible methods
before TIGCC 0.9). Click here for more info.
There is no more need for usage of directives like USE_..._PATCH. The new compiler apply patches automatically when necessary (such directives will be
simply ignored now). In other words, you don't need to worry any more about patches. For this purpose, a new file called tipatch.lib is added to the
library. The new compiler searches through this file to find appropriate patches which eventually should to be included (you should not edit or modify this
file unless you know very well what are you doing).
Three new functions float_to_bcd, bcd_to_float and bcd_var are added to timath.h header file.
A very important function push_internal_simplify which is essential for symbolic mathematic is added to estack.h header file. Note that although this
function is not officially introduced before AMS 2.xx, it is implemented here to work on any AMS version.
Four new functions peekIO, peekIO_w, poke and pokwIO_w are added to peekpoke.h header file, to allow reliable reading and writing to hardware
memory-mapped I/O ports.
A new function EV_getAppID is added in events.h header file, which allows determining application ID numbers regardless of the AMS version. Note that
although this function is not officially introduced before AMS 2.xx, it is implemented here to work on any AMS version.
A new function FolderClear is added in vat.h header file. The structure of SYM_ENTRY is slightly improved (without losing the compatibility).
Functions atof and fabs are now present in stdlib.h header file too, as proposed in ANSI C.
Bugfix: Changed definition of _rowread so it works correctly if used in a short loop with the new compiler.
Bugfix: The directive OPTIMIZE_ROM_CALLS now does not interfere witn an user-written interrupt handlers (thanks to Thomas Nussbaumer). Note however
that it still may interfere with event handlers, and with callback functions used in OSVRegisterTimer, vcbprintf, etc.
Bugfix: Function exit now will not cause a warning if used in the body of a non-void function.
Bugfix: Function FolderDel now works as described (and reliably).
Bugfix: Some functions from ctype.h are rewritten to avoid spurious warnings if the warning-checking level is set too high.
Bugfix: Function hypot will not cause side effects anymore.
Bugfix: Function push_ANSI_string now works correctly in all cases.
Bugfix: Function LCD_save now does not cause spurious warnings if used in "Doors" mode.
Bugfix: Function XR_stringPtr is rewritten to work with all AMS versions (thanks to Romain Herault).
Bugfix: Enumeration StartTypes is rewritten to be compatible with all AMS versions.
The library is changed to replace all 'int's to 'short's where this was appropriate to support the '-mnoshort' command line option supported in the
new version of the compiler.
The documentation is much updated (including correcting of some information which was wrong). The Frequently Asked Questions list is also slightly
updated.
Bugfix: A fatal bug which causes crash if enter_ghost_space function is used on AMS 2.03 is fixed.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 172 of 173
Release 2.21 is just a minor upgrade which includes the documentation in both .chm and .html format, because this was requested by non-Windows
users. Other modifications includes slight fixes in the documentation, and much better organized Frequently Asked Questions list (thanks to James
Darpinian for helping me to organize it).
The documentation for the release 2.2 is completely rearanged to make it much more readable. Moreover, the documentation now contains not only
information about library functions, but about the whole TIGCC project, including the compiler options, a brief reference to C language keywords,
operators and punctuators, description of GNU C language extensions, GNU Assember, and much more. The Frequently Asked Question list is full of new
question/answer pairs. In general, the documentation is now thrice larger than in previous release, and it is now in .chm format (68 separate HTML files
become too inpracticable; if someone is really interested in HTML originals, I can upload them separately). I hope that you will like the new look of the
documentation (and the documentation itself, of course).
The header file all.h is renamed to tigcclib.h to be more consistent. The old name will still be accepted, due to compatibility reasons.
It is not necessary any more to include nostub.h header file explicitely to produce a "nostub" program: the library will do this automatically if you use any
other file from the library, except if you define the global preprocessor symbol USE_KERNEL, or if you explicitely include doors.h header file at the
begining of the program.
A new directive OPTIMIZE_ROM_CALLS is introduced, which optimizes ROM calls in "nostub" mode, which usually leads to shorter and faster programs (but
not always).
Grayscale support on HW2 calculators is improved to be about 50% faster and more flickerless. A new function GrayAdjust is implemented, which allows
fine tuning of grayscale quality, so it allows to reduce flickering as many as possible. Please, recompile your existing grayscale programs if you want to
get advantage of introduced improvements.
It is not necessary any more to put USE_GRAY_PATCH in grayscale programs; the library will now conclude automatically when the grayscale support is
necessary, and it will act accordingly.
Bugfix: trying to enable grayscale now will not cause the crash if the grayscale was already enabled.
A new function GrayCheckRunning and a new enumeration GrayPlanes are added in the gray.h header file.
Bugfix: A fatal bug into functions fwrite and fread which makes them unusuable is fixed. Also, a small bug in fseek (a wrong returned value) is fixed too.
Bugfix: Function fopen is now much more robust if something is going wrong (for example, not enough memory).
A new function enter_ghost_space is introduced, for bypassing some protections introduced in AMS 2.xx.
A new header file intr.h is introduced, which contains functions, language extensions, and data types for easy making of interrupt handlers, and for
general manipulations with interrupts.
Very useful enumeration CommonKeys is introduced in kbd.h header file. It contains keycodes of some commonly used keys.
Bugfix: Function _rowread now works reliable on HW2 calculators (they needs more time for recovering the keyboard controlor).
The documentation now contains the keyboard matrix for usage of _rowread function.
Functions OSVRegisterTimer and OSVFreeTimer are rewriten to works independently of the TIOS, because they are removed from TIOS in AMS 2.04 and
AMS 2.05. Now, they works on any AMS version (in other words: no more "Resident ROM routine not available" message). Please, recompile your
program if you used these function, to make it compatible witn AMS 2.04/5.
A new function alloca is added into alloc.h and stdlib.h header files.
Bugfix: Function assert will not cause a crash anymore when used together with the SAVE_SCREEN directive.
Bugfix: Function assert now works properly if used inside if...else constructions.
Bugfix: Functions assert and ldiv will not trash line numbers anymore.
Bugfix: Functions GetFloatArg, ArgCount and RemainingArgCnt now works correctly in "Doors" mode.
Bugfix: Small corrections are made in functions poke, poke_w and poke_l, to prevent some unnecessary warnings.
Bugfix: Constants CHAR_MIN and CHAR_MAX in limits.h header file are now sensitive to the fact that the compiler may be forced to treat chars as
unsigned.
Bugfix: Although I said that impossibility of making multi-module programs in "Doors" mode is solved in release 2.1, I forgot to do this. This is now really
solved, however.
The library is now programmed on such way that the compiler will emit a warning if you try to return a value using the return keyword from the _main
function, because you in fact can not do this.
The alphabetical list (with appropriate links) of all functions, macro constructors, language extensions, global variables, constants and predefined types is
added to the documentation.
Bugfix: Sprite16 function from sprites.h header file now works correctly. In addition to this bugfix, a new function Sprite8 is added for easier working with
small sprites.
Bugfix: floating point routines caused crash when they are nested deeply (read: very often). This problem is finally solved (after a lot of troubles). I hope
that floating point support is now stable.
Bugfix: FLT macro from timath.h header file generated unnormalized numbers when they are smaller than 0.1. Many floating point routines were not
happy with such numbers, and produced wrong results. This is now corrected.
Bugfix: I hope that I finally found a workarround for a stupid bug in GNU C preprocessor which causes STATUS_ACCESS_VIOLATION exception very often
when FLT macro is used with just one argument. Now, it seems that this problem does not appear any more.
Programs which use floating point support now usually procuce a bit shorter code than earlier.
Bugfix: function div from stdlib.h header file now works correctly.
Bugfix: functions strcmp and memcmp were declared as long, although it seems that these functions leave an unpredictable results in higher half of D0;
they are now declared as int (Sebastian Reichelt and Xavier Vassor informed me about strange behaviour of these two functions). It seems that these
problems are solved after redeclaration.
Bugfix: function ASM_call from system.h header file assumed that called subroutine will preserve all registers, which caused a lot of problems when these
assumptions are violated. ASM_call now saves all registers and restores them after the execution. In addition to this bugfix, a new function ASM_fastcall
is added, for faster calling (when you are sure that a called subroutine will not destroy any registers).
Bugfix: in release 2.0, it was impossible in "Doors" mode to create programs splited in many modules which are linked separately, because symbol _main
was unconditionally exported in doors.h header file. This is now corrected.
Bugfix: function GrayMode from gray.h header file now automatically selects dark plane just after switching on the grayscale mode. Such behaviour in
previous releases of TIGCCLIB was guaranted only on HW1 calculators, but not on HW2 calculators. So, it was possible to produce (quite easily) grayscale
programs which work correctly only on HW1 calculators, although grayscale support is planed to work always on both hardware versions. This is now
fixed.
Some errors in the documentation are fixed, and the documentation is slightly updated (especially information about big number support in rsa.h header
file). As usual, the Frequently Asked Questions list is updated with a lot of useful suggestions.
Starting from this release, TIGCCLIB is much more compatible with ANSI C standard library. Nearly full implementation of stdio.h and stdlib.h is included
(41 new functions in stdio.h and 23 new functions in stdlib.h, together with appropriate data structures and types). So, you can now use a lot of functions
known from various C tutorials: printf, fopen, gets, atoi, qsort, bsearch, strtol...
Usage of patches "inits", "longmul", "longdiv" and "gray" is now much easier: instead of separate linking, it is enough to define some global preprocessor
symbols (like USE_LONGMUL_PATCH etc.).
A directive SAVE_SCREEN is introduced, which allows automatically saving and restoring the content of the screen in "nostub" mode, without needness for
calling LCD_save and LCD_restore manually.
Bugfix: very serious bug which sometimes cause crash in programs which use floating point numbers is corrected (note that this bugfix was released
before, as a separate file called tcl15fix).
A lot of new mathematical functions (mainly for manipulations with symbolic expressions, lists and matrices, and for algebra and calculus applications),
and functions for "pretty printing" expressions are added in estack.h header file (82 new functions). The list of expression tags is completed (more than
500 tags), and the documentation about usage of expression stack is much updated.
A new header file events.h is introduced, with 32 new functions for event driving programming, and calculator mode settings. Now you can simulate TIOS
system events in your programs, and hook into the operating system and change its behavious partially (for example, you can redefine the keyboard, add
new items in system menus, change behaviour of some commands, etc.). But note that these features require good knowledge of programming.
A new header file sprites.h is introduced, with 2 new fast and simple functions for sprite drawing (including masked sprites).
A new header file textedit.h with 16 new functions for accessing the text editor is introduced. As the text editor which is built-in into the TIOS is highly
customizable, you can now write programs with high perfomance editing facilities!
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019
TIGCC Documentation Page 173 of 173
Four language extension macros TRY, ONERR, ENDTRY and PASS are added in error.h header file, to allow error handling similarly like in TI-Basic or in
modern programming languages like Delphi. Also, two new functions are added in error.h, the documentation about it is updated, and some wrong
information are corrected.
A new header file flash.h is introduced, with 11 new functions for low-level access to the Flash ROM. 3 new functions for high-level access to the Flash
ROM are added in vat.h header file.
Some new data structures are added in vat.h header file, various infos related to this header file are updated (especially about organization of VAT table
entries), and one small bug in it is corrected (HS_NULL was wrongly defined).
A new header file cert.h with 17 functions for working for certificate files and other memory-mapped files (not necessary related to certificates) is
introduced.
15 new functions for high-level accessing to the link port are added in link.h header file. Also, some information about link.h are corrected.
A new header file rsa.h is introduced, with 8 new functions for working with very big integer numbers, message diggesting and RSA decryption.
4 new functions are added in args.h header file, which allow more flexible getting of the arguments passed to the program. The list of argument tags is
completed.
Two new header files limits.h and values.h are introduced. They contain various platform-dependent constants (proposed by ANSI). This helps porting
programs from other platforms.
A new header file compat.h is introduced, which defines 18 pseudoconstants (i.e. macros which look and act like constants). These pseudoconstants have
different values on TI-89 and TI-92 Plus, so they can help making compatibility between these two calculator models. Also some pseudoconstants have
different values on AMS 1.xx and AMS 2.xx, so they can help solving some minor incompatibilities between AMS 1.xx and AMS 2.xx during usage of some
functions (although 99% of implemented functions are AMS-independent).
Two very useful global variables are added in wingraph.h header file. Also, some information about this header file and graph.h header file are updated or
corrected.
12 new functions are added in system.h header file, mainly for manipulating with queue structures, the cursor and the clipboard. Many information about
this header file are updated or corrected.
Information about kbd.h header file are much updated. A hint is added about how to avoid slow functions kbhit and ngetchx in high-perfomance keyboard
reading applications, without using very low-level functions like _rowread.
A new header file bascmd.h with 35 new functions is introduced. At the moment, this header file is quite incomplete and a bit unconsistent. In the near
future it will contain more than 150 new functions. This header file contains functions which executes particular TI-Basic statements or functions, so after
completing this header file, nearly everything which may be done using just one TI-Basic statement/function would be possible using just one TIGCC
function (but be aware: the performance will be like during executing of TI-Basic statement/function, so intensive usage of functions from this header file
is not recommended in high-perfomance applications). I started to develop this header file, but the shortage of my free time forces me to stop developing
for a while. I don't want to prolongue releasing of whole TIGCCLIB 2.0 only because this header file is not complete. Be patient, I will continue developing
it as soon as possible...
3 new functions are added in menus.h header file. A lot of information are updated, especially about the exact organization of the menu structure (this
info allows making menus with more levels of submenus).
Function assert is improved, so now there is no any limitations about usage of this function in "nostub" mode.
Function realloc (proposed by ANSI) is added in alloc.h header file (it is also defined in stdlib.h), and calloc is improved to generate smaller code.
Information for assembly programmers are much updated (many people asked me about examples of using floats in ASM programs, so this info is
added).
More than 200 TIOS functions are no more "unknown", so they are moved out of unknown.h header file.
The documentation generally and the Frequently Asked Questions list are updated.
Floating point support is implemented. For this purpose, a new header file timath.h is introduced, with 86 new functions, 4 macro constructors and a lot of
constants and predefined types.
Basic support for the symbolic calculations (including symbolic algebra and calculus) is also implemented. For this purpose, a new header file estack.h is
introduced. It contains 26 functions for manipulations with the expression stack (in the near future, I planed about 50-100 new functions in this header
file).
Bugfix: GraySetAMSPlane function from gray.h now works correctly in "Doors" mode.
Bugfix: grayscale support on Hardware Release 2 calculator is now stable. And, grayscale support now autodetects the hardware version!
Now you can make programs which return a result to the TI-Basic, i.e. which acts like TI-Basic functions. For this purpose, header files nostub.h and
doors.h are slightly changed.
Two very useful functions are added in args.h header file: GetFloatArg and SkipArg. Also, documentation about args.h is much updated and some serious
errors in the documentation are corrected.
2 new functions (ASM_call and EX_patch) are added in system.h.
94 TIOS functions are no more "unknown", so they are moved out of unknown.h header file.
Function NoCallBack is now implemented as cast constructor, so it will not be embeded in the program if not used.
_rowread function from kbd.h is now more reliable.
All arguments which represent a handle or functions which return a handle are now declared as HANDLE instead of unsigned int. Yes, this is exactly the
same, but the documentation is now more clear.
Information about timers in system.h are updated.
Information for assembly programers are slightly updated.
Information about how to use floating point and symbolic arithmetic and information about how to return a value to TI-Basic are added in the
documentation.
Frequently Asked Questions are added to the documentation.
Bugfix: strncmp was incorrectly declared as long, although TIOS strncmp puts the garbage in higher half of D0; it is now declared as int.
Bugfix: type definition for HANDLE in wingraph.h and all.h had a syntax error, which is now fixed.
AMS 2.03 bugfix: NoCallBack is no more in the TIOS jump table, so this fact is now regarded. This fixed problems with usage of dialogs with AMS 2.03. If
you used dialogs.h with previous release of the library, please recompile your program to become compatible with AMS 2.03!
Grayscale support implemented: a new header file gray.h and a new patch gray.o are introduced for this purpose.
Added support of passing arguments to the programs: for this purpose, a new header file args.h is introduced.
Header file assert.h is now included in all.h because I found an inteligent method how to implement assert on such way that it does not increase the
program size if not used in the program (this is a tricky play with conditional assembling).
An information how to make a real stdio.h function printf is added into the documentation about printf.h.
Some additional notes and an example of usage are added for WinOpen function
Global variable top_estack is moved from unknown.h to args.h.
Some typo errors in the documentation are fixed.
file:///C:/Users/Jorge/AppData/Local/Temp/~hhAAF7.htm 23/08/2019