[ First ]  [ Previous ]  [ Next ]  [ Last ]  [ Manuals ]

 

Chapter 9.

 

C and C++ for Win32



This chapter describes both the CodeWarrior® back-end compiler and linker for Win32.

The sections in this chapter are:

However, this chapter does not discuss several important topics with respect to code generation, including front-end compiler issues, compiler and linker errors, controlling the size of C++ code, and so forth. These topics are covered in other CodeWarrior documentation, as outlined in Table 9.1.

Other compiler/linker documentation:

 

For this topic...
See...
how the CodeWarrior IDE implements the C/C++ language  
C Compilers Reference generally  
using C/C++ Language and C/C++ Warnings settings panels  
C Compilers Reference, "Setting C/C++ Compiler Options" chapter  
controlling the size of C++ code  
C Compilers Reference, "C++ and Embedded Systems" chapter  
using compiler pragmas  
C Compilers Reference, "Pragmas and Symbols" chapter  
initiating a build, controlling which files are compiled, and handling error reports  
IDE User Guide, "Compiling and Linking" chapter  
information about a particular error  
Error Reference  
Win32/x86 assembler  
Assembler Guide  


NOTE

Some of the items discussed in this chapter may actually be implemented in the front-end compiler. However, whether the actual implementation of a feature occurs in the front-end or back-end compiler is irrelevant. From the programmer's point of view, it is all one compiler.



Number Formats for Win32/x86

This section describes how the CodeWarrior C/C++ compilers implement integer and floating-point types for Win32/x86 processors. You can also read limits.h for more information on integer types, and float.h for more information on floating-point types. Both of these files are installed with the CodeWarrior IDE and can easily be found using the Find feature of Windows®.

The topics in this section are:


Win32/x86 Integer Formats

The Win32/x86 back-end compiler does not let you change the size of integers. The size of a short int is always 2 bytes and the size of an int or long int is always 4 bytes.

Table 9.2 shows the size and range of the integer types for the Win32/x86 compiler.

Win32/x86 Integer Types:

 

For this type
Option setting
Size is
and its range is
bool  
n/a  
8 bits  
true or false  
char  
Use Unsigned Chars is off  
8 bits  
-128 to 127  
Use Unsigned Chars is on  
8 bits  
0 to 255  
signed char  
n/a  
8 bits  
-128 to 127  
unsigned char  
n/a  
8 bits  
0 to 255  
short  
n/a  
16 bits  
-32,768 to 32,767  
unsigned short  
n/a  
16 bits  
0 to 65,535  
int  
n/a  
32 bits  
-2,147,483,648 to 2,147,483,647  
unsigned int  
n/a  
32 bits  
0 to 4,294,967,295  
long  
n/a  
32 bits  
-2,147,483,648 to 2,147,483,647  
unsigned long  
n/a  
32 bits  
0 to 4,294,967,295  
long long  
n/a  
64 bits  
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807  


Win32/x86 Floating-Point Formats

Table 9.3 shows the sizes and ranges of the floating point types for the Win32/x86 compiler.

Win32/x86 floating point types:

 

Type
Size
Range
float  
32 bits  
1.17549e-38 to 3.40282e+38  
short double  
64 bits  
2.22507e-308 to 1.79769e+308  
double  
64 bits  
2.22507e-308 to 1.79769e+308  
long double  
64 bits  
2.22507e-308 to 1.79769e+308  

 


Calling Conventions for Win32/x86

This section describes the C/C++ calling conventions for Win32/x86 development.

The Win32/x86 back-end compiler supports four calling conventions:

Unless you specify otherwise, the compiler uses the default calling convention. You may choose another calling convention with these declaration specifiers:

__stdcall __thiscall


NOTE

__thiscall is not a supported keyword; it is only available as the default calling convention for C++ methods.



Default calling convention

The default calling convention pushes all parameters onto the stack in right to left order, so the first parameter in the list is on top of the stack when the call is made. It expands each parameter to at least 32 bits on the stack and pads structs to an even number of 32 bit longwords.

When the function call returns, the caller removes the parameters from the stack.

The compiler returns the value of a function in one of three ways:

The default calling convention is also known as the __cdecl calling convention.


Standard calling convention

The standard calling convention is the same as the default calling convention, except that the callee removes parameters from the stack. If you are declaring a function for an API, specify the standard calling convention with __stdcall.


This calling convention

The __thiscall calling convention is the same as the standard calling convention, except that it passes the this pointer in the ECX register.

If you're declaring a non-static member function, the compiler automatically uses the __thiscall calling convention unless you explicitly specify the standard calling convention with __stdcall.


Fast calling convention

The __fastcall calling convention passes the first two arguments that are 4 bytes or smaller in the x86 processor registers ECX and EDX.


Variable Allocation for Win32/x86

(K&R, §A4.3, §A8.3, §A8.6.2) The Win32/x86 back-end compiler places no limits on how large variables can be or how you may allocate them.


Register Variables for Win32/x86

(K&R, §A4.1, §A8.1) This section describes how the C/C++ compilers allocate variables to registers.

The Win32/x86 back-end compiler automatically allocates local variables and parameters to registers according to how frequently they're used and how many registers are available. If you're optimizing for speed, the compiler gives preference to variables used in loops.

The Win32/x86 compiler ignores the register declaration and decides on its own which variables to place in registers.

The compiler will also use the floating point stack (ST(0) through ST(7)) for local variables.

The Win32/x86 compiler can use these registers for local variables:


Optimizing Code for Win32/x86

This section discusses optimizations that are specific to Win32/x86 development with CodeWarrior. These are:

More optimizations are available through the Global Optimizations target settings panel. Refer to the IDE User Guide for more information on optimizations and this panel.


Register Coloring

The C/C++ compiler can perform an optimization called register coloring. In this optimization, the compiler assigns two or more variables to the same register. It does this if the code does not use the variables at the same time. In this example, the compiler could place i and j in the same register:


short i;
int j;
for (i=0; i<100; i++) { MyFunc(i); }
for (j=0; j<100; j++) { MyFunc(j); }

However, if a line of code like the one below appears anywhere in the function, the compiler would realize that you are using i and j at the same time, and place them in different registers.


MyFunc (i + j);

Register coloring reduces code size and has no effect on execution time.

If register coloring is on while you debug your code, it may appear as though there's something wrong with the variables that share a single register. In the example above, i and j would always have the same value. When i changes, j changes in the same way, and vice versa.


Instruction Scheduling

The compiler uses the instruction scheduling optimization to increase the speed of execution. This optimization rearranges processor instructions so that the execution of one instruction doesn't hold up the execution of others, whenever possible. This optimization only has an effect on Win32/x86 processors that are able to process more than one instruction at a time. Namely, Intel Pentium (and compatible) processors have multiple execution units that handle more than one type of instruction at a time.

To turn on instruction scheduling, slide the dial on the Global Optimizations target settings panel to Level 3 or Level 4. To learn more about the Global Optimizations panel, see the IDE User Guide.

The setting you select the Target Processor list-box in the x86 Processor panel controls the scheduling heuristics for a particular processor. For more information about this panel, see "x86 Processor."

To turn off register coloring, disable the SYM Format option in the x86 Processor settings panel.

For specific optimization information regarding AMD® processors, refer to "Targeting AMD Processors."


Alias Analysis

Alias Analysis is a facility that allows the compiler to track pointer values during compilation. By gathering extra information about pointer use, the compiler can apply more intelligent optimizations. Optimizations that were not possible before this improvement are now enabled, with the effect that pointer-based code runs faster.

To illustrate how this can improve your code, we examine some code containing a common sub-expression that can be eliminated. Common sub-expression elimination (CSE) is just one of the optimizations that the CodeWarrior IDE can perform. If your code contains the expression a*b*c multiple times, CSE allows the compiler to generate a temporary value and then replace each occurrence of the expression with this temporary value.

The example in Listing 9.1 demonstrates how CSE works across an assignment through a pointer.

CSE for Pointers:


void TestFunction2( int *int1, int *int2, int *int3, int *int4 )
{
	*int1 = *int3/*int4; // the RHS is the CSE here
	int1 = GetGobalIntPtr(NULL);
	*int1 = 0;
	*int2 = *int3/*int4; // the CSE again
}

Note that *int3/*int4 is a CSE, but involves pointers. Through the use of alias analysis this CSE is optimizable even though it involves pointers.


Linker Issues for Win32/x86

This section discusses the background information on the Win32/x86 linker and how it works. The topics in this section are:


Deadstripping Unused Code and Data

The Win32/x86 linker deadstrips unused code and data only from files compiled by the CodeWarrior C/C++ compiler. Assembler relocatable files and C/C++ object files built by other compilers are never deadstripped. Deadstripping is particularly useful for C++ programs. Libraries (archives) built with the CodeWarrior C/C++ compiler only contribute the used objects to the linked program. If a library has assembly or other C/C++ compiler built files, only those files that have at least one referenced object contribute to the linked program. Completely unreferenced object files are always ignored.


Link Order

Link order is generally specified in the Link Order view of the project window. For general information on setting link order, refer to the IDE User Guide.

Regardless of the link order specified in the Link Order view of the project window, the Win32/x86 linker always processes C/C++ or assembler source files before it processes relocatable files (.obj) or archive files (.lib), which are treated as libraries. Therefore, if a symbol is defined in a source file, the linker will use that definition in preference to a definition in a library.


Pragmas for Win32/x86

To learn more about pragmas supported for Win32 code generation, refer to the C Compiler Reference.

 


[ First ]  [ Previous ]  [ Next ]  [ Last ]  [ Manuals ]

Visit the Metrowerks website at: http://www.metrowerks.com
For assistance contact Metrowerks Technical Support at: cw_support@metrowerks.com
Copyright © 2000, Metrowerks Corp. All rights reserved.

Last updated: July 21, 2000