Chapter 4. Compilation Issues

This chapter outlines the issues dealt with at compile and link times. It covers environment variable usage, compile-time switches, error messages and how to link correctly.

Environment Variables

The SGI_ABI environment variable can be used to specify whether you want an old 32-bit, high performance 32-bit (N32) or 64-bit compilation environment. It is overridden by using the -32 (or -o32), -64 or -n32 option on the command line.

Because there are three distinct ABIs used by programs with accompanying libraries, there are three distinct sets of rld search paths and three sets of environment variables.

The default library search path for o32 (old 32-bit ABI) programs is (/usr/lib:/usr/lib/internal:/lib), which can be overridden by either of the environment variables _RLD_ROOT or LD_LIBRARY_PATH.

The default library search path for 64 (64-bit ABI) programs is (/usr/lib64:/usr/lib64/internal:/lib64), which can be overridden by either of the environment variables _RLD64_ROOT or LD_LIBRARY64_PATH.

The default library search path for n32 (new 32-bit ABI) programs is (/usr/lib32:/usr/lib32/internal:/lib32), which can be overridden by either of the environment variables _RLDN32_ROOT or LD_LIBRARYN32_PATH.

For n32 or 64-bit programs, if LD_LIBRARYN32_PATH or LD_LIBRARY64_PATH is not specified, then rld will honor LD_LIBRARY_PATH if specified.

Command Line Switches

This section lists the differences between the supported switches of the 32-bit and 64-bit compilers.

If you use the -32 switch on the compiler command line, the 32-bit (ucode) compiler is invoked. If you use -64 or -n32, the 64-bit compiler is run.

The default switches on all R8000 based platforms are -64 -mips4. On all other platforms the default switches are -32 -mips2 unless the /etc/compiler.defaults file is present. If it is, its contents will specify what the default values are.

Although they are two separate and different compiler systems, the 32-bit and 64-bit compilers have similar command line interfaces. The following list summarizes the differences between the compilers in the switches that they support. A full list can be found in the cc(1), f77(1) and f90(1) man pages:

Fortran Switch Differences

The 32-bit compiler supports the following switches which the 64-bit compiler does not:

-32, -o32 

By definition.

-mips1 

Generate code using the MIPS1 instruction set.

-mips2 

Generate code using the MIPS2 instruction set (the default for the 32-bit compiler).

-66 

Suppress extensions that enhance FORTRAN 66 compatibility.

-[no]kpicopt 

Asks uopt to perform the special treatment for global variables to optimize their program accesses regardless of the shared or non-shared compilation mode.

-j 

Compile the specified source program and leave the ucode object file in a .u file.

-w66 

Suppress only FORTRAN 66 compatibility warnings messages.

-usefpidx 

Force the compiler to use the floating point DO loop variable as the loop counter.

-vms_cc 

Use VMS Fortran carriage control interpretation on unit 6.

-vms_endfile 

Write a VMS endfile record to the output file when ENDFILE statement is executed and allow subsequent reading from an input file after an endfile record is encountered.

-vms_library 

Treat subroutines/functions starting with LIB$, OTS$, and SMG$ as VMS runtime library routines which take a variable number of arguments.

-vms_stdin 

Allow rereading from stdin after EOF has been encountered.

The 64-bit compiler supports the following switches which the 32-bit compiler does not:

-64 

By definition.

-n32 

Generate code for the high performance 32-bit (N32) ABI.

-mips3 

Generate code using the MIPS3 instruction set.

-mips4 

Generate code using the MIPS4 instruction set (the default for the 64-bit compiler on Power Challenge).

C Switch Differences

The 32-bit compiler supports the following switches which the 64-bit compiler does not:

-32, -o32, -mips1,-mips2 


As in 32-bit Fortran above.

-[no]kpicopt 

Asks uopt to perform the special treatment for global variables to optimize their program accesses regardless of the shared or non-shared compilation mode.

-j 

As in 32-bit Fortran above.

-hpath 

Use path rather than the directory where the name is normally found.

-Bstring 

Append string to all names specified by the -t option.

The 64-bit compiler supports the following switches which the 32-bit compiler does not:

-64, -n32,-mips3 -mips4 


As in 64-bit Fortran above.

-help 

Print a list of possible options.

-keep 

Keep intermediate files.

-show1 

Show phases but don't have phases print additional info.

-showt 

Show time taken by each phase.

-unsigned 

Characters are unsigned by default.

-woffall  

Turn off all warnings.

The following switches are accepted by both compilers but have different semantics:

-O3  

On the 32-bit compiler, a ucode object file is created and left in a .u file. Inter-procedural optimization is done on the resulting ucode linked file and an a.out file is created. On the 64-bit compiler interprocedural optimization is carried out when the -IPA flag is present and can be done at optimization levels less than -O3.

-v 

On the 32-bit compiler, it's the same as -show, whereas it means verbose warnings on the 64-bit compiler.

-woff 

Turn off named warnings, but the warning numbers are different between the compilers.

-Wc,arg1,[,arg2...] 


Designate to which pass, c, of the compiler the arguments are to be passed.

Optimization Switches of the 64-Bit Compilers

In addition to the switches listed above, both the 64-bit Fortran and 64-bit C compilers support many more switches. These switches are used to control the types of optimizations the compilers perform. This section outlines the various optimizations that the 64-bit compilers can perform, and lists the switches used to control them. To get a summary of the flags and their values set the -LIST:all_options=ON flags on the command line. For example:

%f77 -64 -O3 -mips4 -LIST:all_options=ON foo.f

This creates a .l file which contains a summary of all the flags used in the compilation including the default values of flags not explicitly set on the command line.

The optimizations and switches fall into the following categories:

  • General optimizations which are described on the individual compiler man pages (f77(1), f90(1) and cc(1)). These include options to perform local and global optimizations, aggressive optimizations, and options that maximize performance.

  • Floating point optimizations, which include a number of options which trade off source language expression evaluation rules and IEEE 754 conformance against better performance of generated code. These options allow transformations of calculations specified by the source code that may not produce precisely the same floating point result, although they involve a mathematically equivalent calculation. See the opt(5) man page for details about these options.

  • Processor-specific tuning options, which are used to instruct the compiler to schedule code for the given processor and to use processor-specific math libraries (e.g. /usr/lib64/mips4/r10000/libm.so) when linking. The resulting code may be optimized for a particular platform, but may not be optimal for use across all platforms. These options are described on the individual compiler man pages (f77(1), f90(1) and cc(1)).

  • Inter-Procedural Analysis (IPA) optimizations, which control subroutine inlining. See the ipa(5) man page for details.

  • Loop Nest Optimizations (LNO), which allow the user to specify that command-line options override pragmas in a file. See the lno(5) man page for details.

  • Target environment options, which tell the compiler about the target software environment. See the individual compiler man pages (f77(1), f90(1) and cc(1)) for details about the -TENV options.

Data Alignment Options

Two compiler options are concerned with the alignment of data:

-align32 | -align64

The MIPS architectures perform memory references much more efficiently if the data referenced is naturally aligned, that is, if 4-byte objects are at 4-byte-aligned address, etc. By default, the compilers allocate well-aligned data, and that is a requirement of the ABI for C. However, code ported from other architectures without alignment constraints may require less restricted alignment.The ANSI Fortran standard essentially requires maximum alignment of 4 bytes (32 bits), although it is unusual for code to actually depend on this. These options specify a maximum alignment (in bits) to be forced in allocating data. The MIPSpro 64-bit compilers default to -align64 for MIPS3 or MIPS4 Fortran, and to ABI alignment (up to 128 bits for long double) for C.

-TENV:align_aggregates=n

The ABI specifies that aggregates (that is, structs and arrays) be aligned according to the strictest requirements of their components (that is, fields or elements). Thus, an array of short ints (or a struct containing only short ints or chars) is normally 2-byte aligned. However, some non-ANSI-conforming code may reference such objects assuming greater alignment, and some code (for example, struct assignments) may be more efficient if the objects are better aligned). This option specifies that any aggregate of size at least n is at least n-byte aligned. It does not affect the alignment of aggregates which are themselves components of larger aggregates.

Compilation Messages

Because they are two separate and different compiler systems, the 32-bit and 64-bit MIPSpro compilers have different warning and error messages.

The 32-bit C compiler emits errors as follows: the phase of the compiler which detects an error or warning, identifies itself first, then it prints whether it found an error or warning. The next printed items are the file name, line number and description of the error.

Fortran error messages are similar except the compiler phase name is omitted.

Two examples illustrate this:

C:

%cc -32 test.c

cfe: Error: test.c, line 4: Syntax Error

Fortran:

% f77 -32 err.f

Error on line 6 of err.f: syntax error

Under the 64-bit compiler, back end warning messages start with the string "!!!". Error messages start with the string "###". This allows easier searches in log files. C error messages are similar to the 32-bit compiler's error messages, although they are usually more descriptive.

Here the same files compiled with the 64-bit compiler result in the following error messages:

C:

%cat test.c

#include <stdio.h>
main ()
{
    printf ("help")

}

%cc -64 test.c
"test.c", line 4: error(1065): expected a ";"

Fortran:

%cat err.f
        program test
c
c
2       write(6,8)
8       formatr('This is a test')
        end

% f77 -64 err.f
"err.f", line 6: error(2080): expected a "("
8       formatr('This is a test')
                      ^
1 error detected in the compilation of "err.f"
Important Warning Messages

When porting a 32-bit application to 64-bits use the -fullwarn option to expose variable size related issues. Two warnings in particular emitted by the 64-bit C compiler are helpful in this respect. They allow you to locate faulty assumptions that integers and pointers are the same size.

cc-3187 cc: WARNING File = foo2.c, Line =4

A pointer is converted to a smaller integer.

For example, the following code fragment generates this warning when compiled -64.

i = (unsigned) p;

In this example, the unsigned integer variable i is set to only the low order 32 bits of p. If p contains an address greater than 32 bits, that address is truncated in i.

Linking Your Application

The cc driver automatically picks the correct compiler, linker, and library paths if you use the -32, -n32 or -64 switches on the command line. If you compile and link separately, you must use these switches on both the cc driver and ld command lines. If you link with libraries that are not included with IRIX or the compiler, you must make sure that they are of the proper type. Remember, you can't link 32-bit applications with N32 or 64-bit .so's.

To create your own N32, 64-bit or 32-bit libraries, you must supply the correct switch on the archiver command line.

Libraries

The 32-bit and 64-bit compilers include some different libraries. Whereas, the 32-bit compiler includes libftn.so, libF77.a,libI77.a,libU77.a and libisam.a under /usr/lib, the 64-bit compiler has one library, libftn.so, under /usr/lib64 and /usr/lib32.

The 64-bit compiler also introduces routines which do QUAD precision (128-bit) floating point calculations into existing libraries.

The 64-bit compiler provides a united runtime library for parallel C and parallel Fortran programs (/usr/lib64/libmp.so), as opposed to two (/usr/lib/libc_mp.a, /usr/lib/libkapio.a) libraries under the 32 code compiler. This united library allows you to mix parallel C with parallel fortran programs.

The 64-bit compiler also does not include libmld.a, but provides libdwarf.a.