MIPSPro

MIPSPro is the IRIX-native C/C++/FORTRAN compiler that was distributed by SGI for use in IRIX development.

This page serves to document MIPSPro's behavior, characteristics, compatibility, and differences from other UNIX-style cc compilers and the GNU Compiler Collection.

For legacy MIPSPro releases and documentation, there will be an IRIX IDO page covering IDO and legacy MIPSPro releases in the future!

General

MIPSPro is not installed in a standard IRIX install and requires a collection of other discs that contain the compiler, development libraries/header files, toolchain and supporting utilities.

MIPSPro supports three ABIs, O32, N32 and N64 (Not to be confused with the Nintendo 64). The O32 ABI is the MIPSII 32-bit ABI, and stands for Old 32. The N32 ABI is analogous to the Intel x32 ABI used on x64 systems to provide enhancements to 32-bit programs through using 32-bit pointers while offering many of the N64 ABI enhancements over O32. The N64 ABI is the native 64-bit ABI for IRIX.

Several compiler front ends were available, including the C, C++ and FORTRAN compilers. Others may have possibly been available at various points historically.

Optimization

MIPSPro supports -O0,1,2,3, and fast flags, as well as a number of other optimization/architecture flags:

-mips4 will enable the MIPS IV instruction set
-TARG will enable platform or CPU-specific optimizations
-OPT can tune various optimizations

For a full list, please check: https://irix7.com/techpubs/007-2360-006.pdf

TARG flag

The TARG flag controls both platform and CPU specific optimizations and will take a variety of commands:

-TARG:proc=R10000 will, combined with the MIPSIV flag, compile for MIPS IV platforms and enable specific optimizations for the R10000 processors. The resulting binary will run on R5000 and R8000 systems, but will skip the optimizations for those platforms.

-TARG:platform=IP30 will, combined with other flags, enable Octane specific optimizations.

The two commands can be combined as so: -TARG:platform=IP30:proc=R10000 as well as other commands.

OPT flag

This has a number of useful flags for more carefully optimizing code.

-OPT:space Optimizes the program for size, similar to the GCC -Os flag

-OPT:Olimit=n This sets a cutoff limit on procedure sizes to optimize. Procedures above the set size will be left alone. The compiler will normally during compilation throw notices out advising of potential ways to tune this.

-OPT:alias=value The compilers must normally be very conservative in optimization of memory references involving pointers (especially in C), since aliases (that is, different ways of accessing the same memory) may be very hard to detect. This option may be used to specify that the program being compiled avoids aliasing in various ways. See the above document for various applications.

Other flags are listed in the above document

C Programming with MIPSPro

Much like GCC and other modern compilers, MIPSPro can be called from the commandline like so:

% cc foo.c

Where foo.c is a presumably simple test file.

MIPSPro's ABI, compiling and configuration is via /etc/compiler.defaults. This can be overridden with compile-time flags, or ENV variables. SGI_ABI, for instance, controls the active ABI:

% setenv SGI_ABI -n32

This will set it to -n32 mode.

Strictness

MIPSPro is far more strict than GCC about accepting standard C code and its compiler infrastructure is entirely different. Common bad programming techniques that work in GCC may not work on MIPSPro, this section aims to document common pitfalls:

Variable Attributes

These are not supported, so they have to be patched with #ifdef or removed:

__attribute__(( XXX ))

This is the structure of these.

One variable attribute can be rewritten to work with MIPSPro: the attribute 'packed' for a struct can be enforced in MIPSPro by placing the struct between two pragma blocks:

#if defined (__sgi)
+#pragma pack(1)
+#endif

struct {
...
};

#if defined (__sgi)
+#pragma pack(0)

+#endif


Zero Length Arrays
This is a GNU extension prior to c99. Using c99 or -c99 flag for cc should allow it to work.

Variable Length Arrays
Only supported using the c99 driver or -c99.

String Literals
Moderator Dexter1 helpfully pointed this out in a forum post:

Shorthand initialization of char a[] = " "; with MIPSpro will go wrong with leading zero bytes. Rewrite that code.

What follows is his example copied mostly-verbatim:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

int main(void) {
const char a[] = "\0This is a text";
const char b[] = { 0x0, 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a',
' ', 't', 'e', 'x', 't', 0x0 };
const char *c = "\0This is a text";
char buf1[128];
char buf2[128];
char buf3[128];

size_t lena = sizeof(a) - 1;
size_t lenb = sizeof(b) - 1;
size_t lenc = 15;

memcpy(buf1,a,lena);
memcpy(buf2,b,lenb);
memcpy(buf3,c,lenc);

printf("length a : %d, length b %d, length c %d\n", lena, lenb, lenc);
printf("buf11 : %x, buf21 : %x, buf31 : %x\n", buf11, buf21, buf31);
printf("comparing a with buf1 : %d \n", memcmp(a,buf1,lena));
printf("comparing b with buf2 : %d \n", memcmp(b,buf2,lenb));
printf("comparing c with buf3 : %d \n", memcmp(c,buf3,lenc));
printf("comparing buf1 with buf2 : %d \n", memcmp(buf1,buf2,lena));
printf("comparing buf1 with buf3 : %d \n", memcmp(buf1,buf3,lenc));
printf("comparing buf2 with buf3 : %d \n", memcmp(buf2,buf3,lenb));

return 0;

}


Consider this code. The three text containers a, b and c are initialized differently but all should contain "This is a text" preceded and suffixed by a zero byte.

  • Container a's type is an array of char. Its lifetime is limited to the main scope and its initialized content gets put on the stack by the compiler.
  • Container b is the longer version of a and is also typed array of char.
  • Container c is a pointer to a read-only memory block of chars allocated and initialized by the compiler on the heap.


If compiled with MIPSpro cc or c99 and ran, it becomes apparent that array a is not initialized properly. a1 should contain capital 'T' but instead it's a zero byte: once looking at the stack where a is put with a debugger, there is nothing: The preceding zero byte interferes with compiler code and the stack, although it will allocate the correct amount of bytes on the stack, will only contain zeroes.

This 'shorthand' initialization of an array is often used in modern opensource software, and is particularly prevalent in test suites, where binary headers and unicode data content are initialized in arrays to test functions.

String Concatenation
GCC will accept the following code, by concatenating the strings:

puts( "abc" "def" );

This is going to not work on MIPSPro's c89, but will on c99. A tutorial on how to fix it is below:

puts( "abcdef" );

This can work here, alternatively this would too:

char buff[ 255 ];
bzero( buff, 0, 255);
strcat( buff, "abc" );
strcat( buff, "def" );


Arithmetic On Pointers
The gcc compiler allows pointer arithmetic on void pointers. For example, gcc allows

void *foo;
foo += 5;

When using MIPSpro, the pointer must be cast to a type with a size:

void *foo;
foo = (char*)foo + 5;


lvalues
gcc allows the use of casts as lvalues. For example:

void *foo;
(char*)foo += 5;

When using MIPSpro, casts cannot be lvalues:

void *foo;
foo = (char*)foo + 5;

Block Expressions
gcc allows block expressions, such as ({x++});. When using MIPSPro compilers, remove the extra parentheses.

Portable Types
Occasionally code that works on other platforms will compile fine on IRIX, but will misbehave when run. These problems can be difficult to track down, but one thing to check for is assumptions about whether char is signed or unsigned. IRIX compilers default to unsigned. It's recommended to check for this.

Setting up parallel debugging sessions and stepping through the working and non-working code simultaneously to find where they diverge is often helpful.

Alternatively, try to recompile the code with the MIPSPro option -signed in CFLAGS. This will treat variables with type char as if they are signed char.

setenv() missing in IRIX

Raion's libxg library has solved this, see it for an example.

POSIX Threads and Reentrancy
The pthread implementation under Irix is mostly the standard pthreads - there is however a caveat in the form of #defines that are necessary.

CPPFLAGS="-D_SGI_MP_SOURCE -D_SGI_REENTRANT_FUNCTIONS"


SGI recommended these back when their technical documentation library was a thing - and certainly the first define alters the behavior of the general error indicator errno. Without _SGI_MP_SOURCE individual threads receive separate and unique errno addresses.

If there is unusual behavior regarding threads not sharing or unexpectedly sharing data, one may be missing one of the above.

Line terminators
The ANSI specification leaves the determination of valid line terminators to the compiler implementors. MIPSpro allows ^J, while GCC allows both ^J and ^M. The to_unix command will convert files containing DOS-style ^M line terminators to the UNIX standard ^J form.

Pseudo Function Macros
gcc allows the non-standard __FUNCTION__ and __PRETTY_FUNCTION__ pseudo-macros. These are not true macros, so one must use _GNUC__ to test for them. As of IRIX 6.5.18, the c99 func macro is available, which expands to a function name.

Extern Inline Functions
The gcc compiler treats extern inline functions as being extern,while the MIPSpro compilers treat them as inline. To get equivalent behavior, remove the inline keyword.

Inline defines in C code
Pre-c99 C code often define an INLINE macro being set to inline MIPSPro cc compiler instead uses __inline MIPSPro's c99 compiler follows the c99 standard and will inline function with the inline keyword.

getopt_long() missing in IRIX
Raion is aware and looking to add a version from a BSD to add it to irisware.

Compiler Identification
To pass specific code using an identification macro, the __sgi macro can be used to reliably define MIPSPro-related code (or IRIX specific code in general, this can be combined with gnu macros to make paths for both gcc and MIPSPro)

Warning Sanitizing
MIPSPro is very pedantic with warnings. This can be used in Makefiles to make it less pedantic and behave more like GCC:

NOWARN = -woff 1009,1014,1110,1116,1185,1188,1204,1230,1233 \

-Wl,-woff,85,-woff,84

$(CC) $(NOWARN) ...


It is highly encouraged to do a normal pass and capture the warnings it gathers anyways, as these can provide some insight into potential mismatches and other issues.

C99 Specifics

MIPSPro provides C99 compatibility via the c99 driver.

The C99 implementation in MIPSPro is quite good, but unlike standard cc, which is not C99 compliant, it offers far more features:

C++-Style Comments

By default, the cc driver does not allow // comments to be used. To use //, either use the c99 driver, or set flag -Xcpluscomm in the CFLAGS.

Function Macros

As previously stated, all versions of IRIX since 6.5.18 support the function pseudomacro.

Variadic Macros

Supported in c99

Format problems in printf for variables with size_t and ssize_t

In MIPSPro one cannot use the format strings %zu for size_t types and %zd for ssize_t types. Use %lu and cast both types to unsigned long to print out these variables. Failure to do so will result in unexpected crashes when the program reaches those printf statements.

More to be added as they are discovered.

Compiler Drivers

The driver commands cc, c99, CC, f90, and f77 call subsystems that compile, optimize, assemble, and link source. This section describes the default behavior for compiler drivers.

At compilation time, it is possible to select one or more options that affect a variety of program development functions, including debugging, profiling, and optimizing. It's also possible to specify the names assigned to output files. Note that some options have default values that apply if not specified.

When one invokes a compiler driver with source files as arguments, the driver calls other commands that compile the source code into object code. It then optimizes the object code (if requested to do so) and links together the object files, the default libraries, and any other libraries specified.

Given a source file foo.c, the default name for the object file is foo.o. The default name for an executable file is a.out. The following example compiles source files foo.c and bar.c with the default options:

% cc foo.c bar.c

This example produces two object files, foo.o and bar.o, and links them with the default C library, libc , to produce an executable called a.out.