______________________________________________ HP C V7.1-011 for OpenVMS Industry Standard 64 Release Notes November 24, 2004 © Copyright 2004 Hewlett-Packard Company ii ________________________________________________________________ Contents 1 Introduction................................. 1 2 Installation................................. 1 3 Major Differences from Native Alpha Compiler..................................... 3 3.1 #pragma linkage.......................... 3 3.1.1 Register Name Mapping for #pragma linkage................................ 4 3.1.1.1 Integer Register Mapping.............. 5 3.1.1.2 Floating-point Register Mapping....... 7 3.1.1.3 Diagnostics........................... 8 3.1.2 New #pragma linkage_........... 9 3.1.2.1 Register names for #pragma linkage_ia64.......................... 9 3.1.2.2 Register names for #pragma linkage_alpha......................... 9 3.1.3 New keyword "standard_linkage"......... 10 3.2 Builtin Functions........................ 10 3.2.1 Alpha compatibility.................... 10 3.2.2 IA64 specific.......................... 13 3.3 Changed Floating Point Defaults and Controls................................. 15 3.3.1 I64 Default: /FLOAT=IEEE_FLOAT/IEEE=DENORM.......... 15 3.3.2 Semantics of /IEEE_MODE qualifier...... 16 3.4 Predefined Macros........................ 17 4 KNOWN BUGS................................... 17 5 REPORTING PROBLEMS........................... 18 iii 1 Introduction This document contains the release notes for HP C V7.1-011 for OpenVMS I64, which is a native I64 image generating native I64 object modules. When installed, the operation and behavior of the compiler is very similar to that of Compaq C V6.5 for OpenVMS Alpha. The native HP C compiler in this kit identifies itself as: HP C V7.1-011 for OpenVMS I64 ________________________Note ________________________ This kit does not provide any header files. All header files that were provided by C compiler kits for previous versions of OpenVMS are now supplied as part of the OpenVMS base system. _____________________________________________________ For additional information on the compiler, see also: o HP C User's Guide for OpenVMS Systems o Enter the command HELP CC at the $ prompt. For additional information about the HP C language and its supported library routines, see also: o HP C Language Reference Manual o HP C Run-Time Library Reference Manual for OpenVMS Systems 2 Installation To install HP C V7.1 for OpenVMS I64 systems, set the default directory to a writeable directory to allow the IVP to succeed. Then run the PRODUCT INSTALL command, pointing to the kit location. For example: 1 $ SET DEFAULT SYS$MANAGER $ PRODUCT INSTALL C/SOURCE=node::device:[kit_dir] After installation, these C++ release notes will be available at: SYS$HELP:CC.RELEASE_NOTES SYS$HELP:CC_RELEASE_NOTES.PS Here is a sample installation log: $ PRODUCT INSTALL C/SOURCE=DEVO$:[CC.KITTING] The following product has been selected: HP I64VMS C V7.1-155 Layered Product Do you want to continue? [YES] Configuration phase starting ... You will be asked to choose options, if any, for each selected product and for any products that may be installed to satisfy software dependency requirements. HP I64VMS C V7.1-155: HP C for OpenVMS Industry Standard Copyright 2003 Hewlett-Packard Development Company, L.P. This software product is sold by Hewlett-Packard Company PAKs used: DECC or DECC-USER Do you want the defaults for all options? [YES] Copyright 2004 Hewlett-Packard Development Company, L.P. HP, the HP logo, Alpha and OpenVMS are trademarks of Hewlett-Packard Development Company, L.P. in the U.S. and/or other countries. Confidential computer software. Valid license from HP required for possession, use or copying. Consistent with FAR 12.211 and 12.212, Commercial Computer Software, Computer Software Documentation, and Technical Data for Commercial Items are licensed to the U.S. Government under vendor's standard commercial license. Do you want to review the options? [NO] Execution phase starting ... 2 The following product will be installed to destination: HP I64VMS C V7.1-155 DISK$ICXXC_SYS:[VMS$COMMON.] The following product will be removed from destination: HP I64VMS C V7.1-145 DISK$ICXXC_SYS:[VMS$COMMON.] Portion done: 0%...40%...50%...60%...70%...80%...90%...100% The following product has been installed: HP I64VMS C V7.1-155 Layered Product The following product has been removed: HP I64VMS C V7.1-145 Layered Product %PCSI-I-IVPEXECUTE, executing test procedure for HP I64VMS C V7.1-155 ... %PCSI-I-IVPSUCCESS, test procedure completed successfully HP I64VMS C V7.1-155: HP C for OpenVMS Industry Standard The release notes are located in the file SYS$HELP:CC.RELEASE_NOTES for the text form and SYS$HELP:CC_RELEASE_NOTES.PS for the postscript form. 3 Major Differences from Native Alpha Compiler This native C compiler for I64 behaves very much like the current native Alpha C compiler (V6.5) in terms of command line options, language features, etc. Primary differences are in the support for #pragma linkage, builtin functions, default floating-point representation and controls, and predefined macros. 3.1 #pragma linkage The behavior of this pragma has been changed dramatically to help deal with the large VMS code base that has used the pragma with the assumption that the target platform would be Alpha, adhering to the OpenVMS Calling Standard for Alpha (this pragma does not exist in the VAX compiler). Also, new variants of the pragma have been added that help clarify the platform-dependent nature of what the pragma specifies; these new pragmas can only be used in code that is properly conditionalized to the target platform. 3 Because a mismatched linkage between caller and callee tends to cause hard-to-diagnose problems at run-time, and because linkage mismatches often occur when calling undocumented interfaces written in a low-level language for which the user may not have source code, the compiler generates a .vms_linkage section that assists the linker in diagnosing conflicts in linkage specifications between function definitions and function calls across compilation units. 3.1.1 Register Name Mapping for #pragma linkage The #pragma linkage directive is inherently platform- dependent because it uses the names of specific target- machine registers and specifies how they are to be treated in a particular call interface. There may be both hardware and calling-standard constraints that conflict with the behavior specified by #pragma linkage. E.g. on Alpha, register R0 is specified in the calling standard as the first function return value register; but on IA64, R0 is a read-only zero-value register that cannot be assigned a different value (similar to R31 on Alpha). Like uses of the inline asm function on Alpha, uses of this pragma ought to have been coded conditionally for the target system, to be reviewed and modified or removed whenever porting to a different target. However, in practice it was found that a significant amount of C code exists that uses this pragma uncondi- tionally (or conditionalized on #ifndef __VAX) assuming Alpha register names and calling standard conventions. To reduce the number of source code changes actually required to make this code functional for IA64, it was decided that the pragma would be modified for the IA64 target to accept Alpha register names and conventions, and automatically map these whenever possible to specific IA64 registers according to a correspondence established at the calling- standard level. At the same time, a new version of the pragma, #pragma linkage_ia64 was implemented. This pragma specifically interprets register names as IA64 hardware registers. 4 When HP C for I64 encounters the older #pragma linkage directive, by default it will emit a SHOWMAPLINKAGE informational message showing the IA64-specific form of the directive, #pragma linkage_ia64, with the IA64 register names that replaced the Alpha register names. Ideally, over time each such message should be examined to determine whether or not a special linkage is necessary or desirable when the application is built for OpenVMS I64, and source code changes made along one of the following lines: o If the linkage is required to meet an externally- imposed interface, change the source to use #pragma linkage_ia64 as shown by the SHOWMAPLINKAGE message, under target-specific conditional compilation (e.g. #if __ia64). o If the purpose of the linkage on Alpha is to improve performance or debugging characteristics, and your source code contains the definition of the called function as well as providing the declaration and linkage used by all callers of the function, then consider whether the linkage as it was mapped by the compiler to the IA64 registers is likely to provide a significant benefit on IA64. Within a #if __ia64 conditional, you may want to specify a different linkage_ia64 that would likely give more of a benefit on IA64 than the default mapping from Alpha registers. Or you may decide that there is no significant advantage to using a special linkage on IA64, and specify the new keyword standard_linkage. (See Section 3.1.3) 3.1.1.1 Integer Register Mapping The following table shows the mapping that HP C applies to the (Alpha) integer register names used in #pragma linkage directives when they are encountered in HP C for OpenVMS I64. Note that the six standard parameter registers on Alpha (R16-R21) are mapped to the first six (of eight) standard parameter registers on IA64, which happen to be stacked registers (see Section 3.1.2.1 for the naming convention used for stacked registers). This mapping attempts to maximize 5 source code compatibility for linkages that may be used in existing C code for Alpha. Alpha IA64 ----- ---- R0 R8 R1 R9 R2 R28 R3 R3 R4 R4 R5 R5 R6 R6 R7 R7 R8 R26 R9 R27 R10 R10 R11 R11 R12 R30 R13 R31 R14 R20 R15 R21 R16 R32 (in parameter or result, else ignored) R17 R33 (in parameter or result, else ignored) R18 R34 (in parameter or result, else ignored) R19 R35 (in parameter or result, else ignored) R20 R36 (in parameter or result, else ignored) R21 R37 (in parameter or result, else ignored) R22 R22 R23 R23 R24 R24 R25 R25 R26 no mapping R27 no mapping R28 no mapping R29 R29 R30 R12 R31 R0 6 3.1.1.2 Floating-point Register Mapping Alpha IA64 ----- ---- F0 F8 F1 F9 F2 F2 F3 F3 F4 F4 F5 F5 F6 F16 F7 F17 F8 F18 F9 F19 F10 F6 F11 F7 F12 F20 F13 F21 F14 F14 F15 F15 F16 F8 F17 F9 F18 F10 F19 F11 F20 F12 F21 F13 F22 F22 F23 F23 F24 F24 F25 F25 F26 F26 F27 F27 F28 F28 F29 F29 F30 F30 F31 F0 7 3.1.1.3 Diagnostics In some cases, the Alpha compiler silently ignores linkage registers, e.g. if a standard parameter register like R16 is specified in a "pre- served" option. When compiled for IA64, this will get a MAPREGIGNORED informational, and the SHOWMAPLINKAGE output may not be correct. If there is no valid mapping to IA64 registers, the NOMAPPOSSIBLE warning is given, and the linkage is ignored. There are two special situations that can arise when floating-point registers are specified in a linkage. o Only IEEE-format values are passed in floating-point registers under the OpenVMS Calling Standard for IA64. VAX-format values are passed in integer registers. Therefore, if a compilation uses VAX-format floating point (/G_FLOAT, /FLOAT=G_FLOAT, or /FLOAT=D_FLOAT command line qualifiers), any linkage pragma that specifies floating-point registers will produce an error (E-level diagnostic). Note that this includes the use of floating-point registers in linkage options that do not involve passing values, such as the preserved and notused options. o The mapping of floating-point registers is many-to- one in two cases: Alpha registers f0 and f16 both map to IA64 f8, and Alpha f1 and f17 both map to IA64 f9. A valid Alpha linkage may well specify uses for both f0 and f16, and/or both f1 and f17. Such a linkage cannot be mapped to IA64. But because of the way this situation is detected, the MULTILINKREG warning message that is produced can only identify the second occurrence of an Alpha register that got mapped to the same IA64 register as some previous Alpha register. The actual pair of Alpha registers in the source are not identified, and so the message can be very confusing. E.g. an option like preserved(f1,f17) will get a MULTILINKREG diagnostic saying that f17 was specified more than once. 8 3.1.2 New #pragma linkage_ There are two new variants of the linkage pragma, #pragma linkage_alpha and #pragma linkage_ia64. These variants require that register names be specified in terms of the target machine named in the pragma - the register names will never be mapped to a different target. These pragmas produce the UNAVAILPRAGMA informational and are ignored if encountered when compiling code for a target other than the one specified. 3.1.2.1 Register names for #pragma linkage_ia64 For #pragma linkage_ia64, valid registers for the preserved, nopreserve, notused, parameters, and result options include integer registers R3 through R12 and R19 through R31, and floating-point registers F2 through F31. In addition, the parameters and result options also permit integer registers R32 through R39 to be specified, according to the following convention. On IA64, the first eight integer input/output slots are allocated to stacked registers, and thus the calling routine refers to them using different names than the called routine. The convention for naming these registers in either the parameters or result option of a linkage_ia64 directive is always to use the hardware names as they would be used within the CALLED routine: R32 through R39. The compiler automatically compensates for the fact that within the calling routine these same registers are designated using different hardware names. 3.1.2.2 Register names for #pragma linkage_alpha The rules for allowed uses of register names with #pragma linkage_alpha remain as documented for #pragma linkage in the native Alpha compiler. It specifies Alpha register names and does no mapping. The only difference between linkage and linkage_alpha is the behavior when processed for a target machine other than Alpha. For source code compatibility, a future version of the Alpha compiler will add #pragma linkage_alpha, and recognize the new keyword "standard_linkage". (See Section 3.1.3) 9 3.1.3 New keyword "standard_linkage" All forms of the linkage directive now accept a new keyword "standard_linkage", which tells the compiler to use the normal linkage conventions appropriate to the target platform, as specified in the calling standard. When standard_linkage is specified, it must be the only option in the parenthesized list following the linkage name. This can be useful to confine conditional compilation to the pragmas that define linkages, without requiring the corresponding use_linkage pragmas to be conditionally compiled as well. Code that is written to use linkage pragmas as intended, treating them as target-specific without implicit mapping, might have a form like this: #if defined(__alpha) #pragma linkage_alpha special1 = (__preserved(__r1,__r2)) #elif defined(__ia64) #pragma linkage_ia64 special1 = (__preserved(__r9,__r28)) #else #pragma message ("unknown target, assuming standard linkage") #pragma linkage special1 = (standard_linkage) #endif Code compiled for IA64 that deliberately relies on the register mapping performed by #pragma linkage should either ignore the SHOWMAPLINKAGE informational, or disable it (#pragma message disable(SHOWMAPLINKAGE)) 3.2 Builtin Functions 3.2.1 Alpha compatibility The philosophy for the builtin functions is that most any existing uses of Alpha builtins should continue to work under IA64 where possible, but that the compiler will issue diagnostics where it would be preferable to use a different builtin for IA64. For this reason, the builtins.h header has not removed or conditionalized out any of the Alpha declarations. Instead, it contains comments noting which ones are not available or not the preferred form for IA64. Furthermore, a significant number of the __PAL builtins for Alpha have been implemented as system services on OpenVMS I64 instead of actual compiler builtins, but using an implementation technique that is 10 transparent to source code that calls the builtins on Alpha. Specific changes: o There is no support for the asm/fasm/dasm intrinsics (actually declared in ), or any similar mechanism to insert arbitrary sequences of machine instructions into the generated code. Generation of specific machine instructions can only be accomplished using the builtins declared in builtins.h, or by calling functions written in assembly language. o The functionality provided by the special-case treatment of R26 in an Alpha asm, as in asm("MOV R26,R0"), is provided by a new builtin function: __int64 __RETURN_ADDRESS(void). It will also be supported in a future version of HP C for Alpha. The builtin produces the address to which the function containing the builtin call will return (the value of R26 on entry to the function on Alpha, the value of B0 on entry to the function on IA64). It cannot be used within a function specified to use non-standard linkage, or in a varargs function. o There is no compiler-based support for any of the __PAL calls other than the 24 queue-manipulation builtins. The queue-manipulation builtins generate calls to new VMS system services SYS$, where is the name of the builtin with the leading underscores removed. Any other __PAL calls declared in builtins.h are actually supported through macros defined in the header pal_builtins.h provided in sys$library:sys$starlet_c.tlb. Note that builtins.h contains a #include at the end. Typically, a macro in pal_builtins.h effectively hides a declaration in builtins.h, and transforms an invocation of an Alpha builtin into a call to a system service (declared in pal_services.h) that will perform the equivalent function on OpenVMS I64. Two notable exceptions are __PAL_GENTRAP and __PAL_BUGCHK, which instead invoke the IA64-specific compiler builtin __break2(). 11 o There is no support for the various floating-point builtins used by the math library (e.g. operations with chopped rounding and conversions). o Most builtins that take a retry count provoke a warning, and the compiler evaluates the count for possible side effects and then ignores it, invoking the same function without a retry count. This is because the retry behavior allowed by Alpha load-locked/store- conditional sequences does not exist on the IA64 architecture. The "exceptions" to this are __LOCK_ LONG_RETRY and __ACQUIRE_SEM_LONG_RETRY, because in these cases the retry behavior involves comparisons of data values, not just load-locked/store-conditional. o The __CMP_STORE_LONG and __CMP_STORE_QUAD builtins produce either a warning or an error, depending on whether or not the compiler can determine that the source and destination addresses are identical. If the addresses can be seen to be identical, the compiler treats it as the new __CMP_SWAP_ form and issues a warning. Otherwise it is an error. The __CMP_SWAP_ forms are not supported in V6.5 of Compaq C for Alpha; but they are intended to be supported in a future update of HP C for Alpha. o Note that the comments in builtins.h reflect only what is explicitly present in that header itself, and in the compiler implementation. The user should also consult the content and comments in pal_builtins.h to determine more accurately what functionality is effectively provided by including builtins.h. E.g. if a program explicitly declares one of the Alpha builtins and invokes it without having included builtins.h, the compiler may issue the BIFNOTAVAIL error regardless of whether or not the functionality might be available through a system service. If the compilation does include builtins.h, and BIFNOTAVAIL is issued, then most likely there is no support for that functionality; but another (remote) possibility is that there is a problem in the version of pal_builtins.h that is being included by builtins.h. 12 3.2.2 IA64 specific The header file contains a section at the top condition- alized just to __ia64 with all of the planned support for IA64-specific builtins. This includes macro definitions for all of the registers that can be specified to the __getReg/__setReg/__getIndReg/__setIndReg builtins. Parameters that are const-qualified require an argument that is a compile-time constant. /* Intel-compatible */ unsigned __int64 __getReg(const int __whichReg); void __setReg(const int __whichReg, unsigned __int64 __value); unsigned __int64 __getIndReg(const int __whichIndReg, __int64 __index); void __setIndReg(const int __whichIndReg, __int64 __index, unsigned __int64 __value); void __break(const int __break_arg); /* Native IA64 arg */ void __dsrlz(void); void __fc(__int64 __address); void __fwb(void); void __invalat(void); void __invala(void); /* alternate spelling of __invalat */ void __isrlz(void); void __itcd(__int64 __address); void __itci(__int64 __address); void __itrd(__int64 __whichTransReg, __int64 __address); void __itri(__int64 __whichTransReg, __int64 __address); void __ptce(__int64 __address); void __ptcl(__int64 __address, __int64 __pagesz); void __ptcg(__int64 __address, __int64 __pagesz); void __ptcga(__int64 __address, __int64 __pagesz); void __ptri(__int64 __address, __int64 __pagesz); void __ptrd(__int64 __address, __int64 __pagesz); void __rsm(const int __mask); void __rum(const int __mask); void __ssm(const int __mask); void __sum(const int __mask); void __synci(void); __int64 /*address*/ __thash(__int64 __address); __int64 /*address*/ __ttag(__int64 __address); 13 /* These Intel _Interlocked intrinsics will be added to Alpha. */ unsigned __int64 _InterlockedCompareExchange_acq( unsigned int *__Destination, unsigned __int64 __Newval, unsigned __int64 __Comparand); unsigned __int64 _InterlockedCompareExchange64_acq( unsigned __int64 *__Destination, unsigned __int64 __Newval, unsigned __int64 __Comparand); unsigned __int64 _InterlockedCompareExchange_rel( unsigned int *__Destination, unsigned __int64 __Newval, unsigned __int64 __Comparand); unsigned __int64 _InterlockedCompareExchange64_rel( unsigned __int64 *__Destination, unsigned __int64 __Newval, unsigned __int64 __Comparand); /* GEM-added builtins */ void __break2(__Integer_Constant __break_code, unsigned __int64 __r17_value); void __flushrs(void); void __loadrs(void); int __prober(__int64 __address, unsigned int __mode); int __probew(__int64 __address, unsigned int __mode); unsigned int __tak(__int64 __address); __int64 /*address*/ __tpa(__int64 __address); /* ** The following were added to the GEM compiler for IA64, but will ** also be implemented for Alpha. ** ** Nota Bene: ** _Interlocked* built-ins return the old value and have the ** newval and comparand arguments in a different order than ** __CMP_SWAP* built-ins that return the status (1 or 0). ** Forms without trailing _ACQ or _REL are equivalent to ** the _ACQ form. On Alpha, _ACQ generates MB after the swap, ** _REL generates MB before the swap. */ int __CMP_SWAP_LONG(volatile void *__addr, int __comparand, int __newval); 14 int __CMP_SWAP_QUAD(volatile void *__addr, __int64 __comparand, __int64 __newval); int __CMP_SWAP_LONG_ACQ(volatile void *__addr, int __comparand, int __newval); int __CMP_SWAP_QUAD_ACQ(volatile void *__addr, __int64 __comparand, __int64 __newval); int __CMP_SWAP_LONG_REL(volatile void *__addr, int __comparand, int __newval); int __CMP_SWAP_QUAD_REL(volatile void *__addr, __int64 __comparand, __int64 __newval); /* ** Produce the value of R26 (Alpha) or B0 (IA64) on entry to the ** function containing a call to this builtin. Cannot be invoked ** from a function with non-standard linkage. */ __int64 __RETURN_ADDRESS(void); 3.3 Changed Floating Point Defaults and Controls 3.3.1 I64 Default: /FLOAT=IEEE_FLOAT/IEEE=DENORM The native Alpha compiler defaults to /FLOAT=G_FLOAT. But on IA64, there is no hardware support for floating point representations other than IEEE. The VAX floating point formats are supported in the compiler by generating run-time code to convert to IEEE format in order to perform arithmetic operations, and then convert the IEEE result back to the appropriate VAX format. This imposes additional run-time overhead, and some loss of accuracy compared to performing the operations in hardware on the Alpha (and VAX). The software support for the VAX formats is an important functional compatibility requirement for certain applications that need to deal with on-disk binary floating-point data, but its use should not be encouraged by letting it remain the default. This change is similar to the change in default from /FLOAT=D_FLOAT on VAX to /FLOAT=G_FLOAT on Alpha. 15 Note also that the default /IEEE_MODE has changed from FAST to DENORM_RESULTS. This means that by default, floating point operations may silently generate values that print as Infinity or Nan (the industry-standard behavior) instead of issuing a fatal run-time error as they would using VAX format float or /IEEE_MODE=FAST. Also, the smallest-magnitude non-zero value in this mode is much smaller because results are permitted to enter the denormal range instead of being flushed to zero as soon as the value is too small to represent with normalization. 3.3.2 Semantics of /IEEE_MODE qualifier On Alpha, the /IEEE_MODE qualifier generally has its greatest effect on the generated code of a compilation. When calls are made between functions compiled with different /IEEE_MODE qualifiers, each function produces the /IEEE_MODE behavior with which it was compiled. On I64, the /IEEE_MODE qualifier primarily affects only the setting of a hardware register at program startup. In general, the /IEEE_MODE behavior for a given function will be controlled by the /IEEE_MODE option that was specified on the compilation that produced the main program: the startup code for the main program sets the hardware register according the command line qualifiers used to compile the main program. When applied to a compilation that does not contain a main program, the /IEEE_MODE qualifier does have some effect: it may affect the evaluation of floating-point constant expressions, and it is used to set the EXCEPTION_MODE used by the math library for calls from that compilation. But the qualifier will have no effect on the exceptional behavior of floating-point calculations generated as inline code for that compilation. Therefore, if floating point exceptional behavior is important to an application, all of its compilations, including the one containing the main program, should be compiled with the same /IEEE_MODE setting. Note that even on Alpha, the particular setting of /IEEE_MODE=UNDERFLOW_TO_ZERO has this characteristic: its primary effect requires the setting of a run-time status register, and so it needs to be specified on the 16 compilation containing the main program in order to be effective in other compilations. 3.4 Predefined Macros The compiler predefines a number of macros, with the same meanings as in the native Alpha compiler, except that it does not predefine any of the macros that specify the Alpha architecture, but instead it predefines the macros __ia64 and __ia64__, as is the practice in the Intel and gcc compilers for IA64. Also note that the change in floating-point representation from G_FLOAT to IEEE is reflected in the macros that are predefined by default. In particular, _IEEE_FP is now set by default (as it is on Alpha for /float=ieee/ieee=denorm). We note that some users have tried defining the macro __ALPHA explicity with /define or in a header file as a quick "hack" to deal with source code conditionals that were written to assume that if __ALPHA is not defined then the target must be a VAX. Doing this will cause the CRTL headers and other VMS headers to take the wrong path for IA64 - you must not define any of the Alpha architecture predefined macros when using this compiler. 4 KNOWN BUGS o If the /FIRST_INCLUDE qualifier is used to specify more than one header-file, and the first logical source line of the primary source file spans physical lines (i.e. it either begins a C-style delimited comment that is not completed on that line, or the last character before the end-of-line is a backslash line-continuation character), then the compiler will give an internal error. Workarounds are either to make sure the first logical line of the primary source file does not span physical lines (e.g. make it a blank line), or to avoid specifying more than one header in the /FIRST_INCLUDE qualifier (e.g. use a single /FIRST_INCLUDE header that #includes all of the headers you want to precede the first line of the primary source file). 17 5 REPORTING PROBLEMS Please report problems or offer feedback using the mechanisms specified in the "Read Before Installing" document. 18