1 #ifndef COMPILER_H 2 #define COMPILER_H 3 4 /* 5 * Doxygen can't cope with some of the more esoteric areas of C, so we 6 * make its life simpler. 7 * 8 */ 9 #ifdef DOXYGEN 10 #define __attribute__(x) 11 #endif 12 13 /** @file 14 * 15 * Global compiler definitions. 16 * 17 * This file is implicitly included by every @c .c file in Etherboot. 18 * It defines global macros such as DBG(). 19 * 20 * We arrange for each object to export the symbol @c obj_OBJECT 21 * (where @c OBJECT is the object name, e.g. @c rtl8139) as a global 22 * symbol, so that the linker can drag in selected object files from 23 * the library using <tt> -u obj_OBJECT </tt>. 24 * 25 */ 26 27 /* Force visibility of all symbols to "hidden", i.e. inform gcc that 28 * all symbol references resolve strictly within our final binary. 29 * This avoids unnecessary PLT/GOT entries on x86_64. 30 * 31 * This is a stronger claim than specifying "-fvisibility=hidden", 32 * since it also affects symbols marked with "extern". 33 */ 34 #ifndef ASSEMBLY 35 #if __GNUC__ >= 4 36 #pragma GCC visibility push(hidden) 37 #endif 38 #endif /* ASSEMBLY */ 39 40 #undef _S1 41 #undef _S2 42 #undef _C1 43 #undef _C2 44 45 /** Concatenate non-expanded arguments */ 46 #define _C1( x, y ) x ## y 47 /** Concatenate expanded arguments */ 48 #define _C2( x, y ) _C1 ( x, y ) 49 50 /** Stringify non-expanded argument */ 51 #define _S1( x ) #x 52 /** Stringify expanded argument */ 53 #define _S2( x ) _S1 ( x ) 54 55 /** 56 * @defgroup symmacros Macros to provide or require explicit symbols 57 * @{ 58 */ 59 60 /** Provide a symbol within this object file */ 61 #ifdef ASSEMBLY 62 #define PROVIDE_SYMBOL( _sym ) \ 63 .globl _sym ; \ 64 .comm _sym, 0 65 #else /* ASSEMBLY */ 66 #define PROVIDE_SYMBOL( _sym ) \ 67 char _sym[0] 68 #endif /* ASSEMBLY */ 69 70 /** Require a symbol within this object file 71 * 72 * The symbol is referenced by a relocation in a discarded section, so 73 * if it is not available at link time the link will fail. 74 */ 75 #ifdef ASSEMBLY 76 #define REQUIRE_SYMBOL( _sym ) \ 77 .section ".discard", "a", @progbits ; \ 78 .extern _sym ; \ 79 .long _sym ; \ 80 .previous 81 #else /* ASSEMBLY */ 82 #define REQUIRE_SYMBOL( _sym ) \ 83 extern char _sym; \ 84 static char * _C2 ( _C2 ( __require_, _sym ), _C2 ( _, __LINE__ ) ) \ 85 __attribute__ (( section ( ".discard" ), used )) \ 86 = &_sym 87 #endif 88 89 /** Request that a symbol be available at runtime 90 * 91 * The requested symbol is entered as undefined into the symbol table 92 * for this object, so the linker will pull in other object files as 93 * necessary to satisfy the reference. However, the undefined symbol 94 * is not referenced in any relocations, so the link can still succeed 95 * if no file contains it. 96 * 97 * A symbol passed to this macro may not be referenced anywhere 98 * else in the file. If you want to do that, see IMPORT_SYMBOL(). 99 */ 100 #ifdef ASSEMBLY 101 #define REQUEST_SYMBOL( _sym ) \ 102 .equ __need_ ## _sym, _sym 103 #else /* ASSEMBLY */ 104 #define REQUEST_SYMBOL( _sym ) \ 105 __asm__ ( ".equ\t__need_" #_sym ", " #_sym ) 106 #endif /* ASSEMBLY */ 107 108 /** Set up a symbol to be usable in another file by IMPORT_SYMBOL() 109 * 110 * The symbol must already be marked as global. 111 */ 112 #define EXPORT_SYMBOL( _sym ) PROVIDE_SYMBOL ( __export_ ## _sym ) 113 114 /** Make a symbol usable to this file if available at link time 115 * 116 * If no file passed to the linker contains the symbol, it will have 117 * @c NULL value to future uses. Keep in mind that the symbol value is 118 * really the @e address of a variable or function; see the code 119 * snippet below. 120 * 121 * In C using IMPORT_SYMBOL, you must specify the declaration as the 122 * second argument, for instance 123 * 124 * @code 125 * IMPORT_SYMBOL ( my_func, int my_func ( int arg ) ); 126 * IMPORT_SYMBOL ( my_var, int my_var ); 127 * 128 * void use_imports ( void ) { 129 * if ( my_func && &my_var ) 130 * my_var = my_func ( my_var ); 131 * } 132 * @endcode 133 * 134 * GCC considers a weak declaration to override a strong one no matter 135 * which comes first, so it is safe to include a header file declaring 136 * the imported symbol normally, but providing the declaration to 137 * IMPORT_SYMBOL is still required. 138 * 139 * If no EXPORT_SYMBOL declaration exists for the imported symbol in 140 * another file, the behavior will be most likely be identical to that 141 * for an unavailable symbol. 142 */ 143 #ifdef ASSEMBLY 144 #define IMPORT_SYMBOL( _sym ) \ 145 REQUEST_SYMBOL ( __export_ ## _sym ) ; \ 146 .weak _sym 147 #else /* ASSEMBLY */ 148 #define IMPORT_SYMBOL( _sym, _decl ) \ 149 REQUEST_SYMBOL ( __export_ ## _sym ) ; \ 150 extern _decl __attribute__ (( weak )) 151 #endif 152 153 /** @} */ 154 155 /** 156 * @defgroup objmacros Macros to provide or require explicit objects 157 * @{ 158 */ 159 160 #define PREFIX_OBJECT( _prefix ) _C2 ( _prefix, OBJECT ) 161 #define OBJECT_SYMBOL PREFIX_OBJECT ( obj_ ) 162 #define REQUEST_EXPANDED( _sym ) REQUEST_SYMBOL ( _sym ) 163 #define CONFIG_SYMBOL PREFIX_OBJECT ( obj_config_ ) 164 165 /** Always provide the symbol for the current object (defined by -DOBJECT) */ 166 PROVIDE_SYMBOL ( OBJECT_SYMBOL ); 167 168 /** Pull in an object-specific configuration file if available */ 169 REQUEST_EXPANDED ( CONFIG_SYMBOL ); 170 171 /** Explicitly require another object */ 172 #define REQUIRE_OBJECT( _obj ) REQUIRE_SYMBOL ( obj_ ## _obj ) 173 174 /** Pull in another object if it exists */ 175 #define REQUEST_OBJECT( _obj ) REQUEST_SYMBOL ( obj_ ## _obj ) 176 177 /** @} */ 178 179 /** Select file identifier for errno.h (if used) */ 180 #define ERRFILE PREFIX_OBJECT ( ERRFILE_ ) 181 182 /** 183 * @defgroup weakmacros Macros to manage weak symbol definitions 184 * 185 * Weak symbols allow one to reference a function in another file 186 * without necessarily requiring that file to be linked in. In their 187 * native form, the function will be @c NULL if its file is not linked 188 * in; these macros provide an inline wrapper that returns an 189 * appropriate error indication or default value. 190 * 191 * @{ 192 */ 193 #ifndef ASSEMBLY 194 195 /** Mangle @a name into its weakly-referenced implementation */ 196 #define __weak_impl( name ) _w_ ## name 197 198 /** 199 * Declare a weak function with inline safety wrapper 200 * 201 * @v ret Return type of weak function 202 * @v name Name of function to expose 203 * @v proto Parenthesized list of arguments with types 204 * @v args Parenthesized list of argument names 205 * @v dfl Value to return if weak function is not available 206 */ 207 #define __weak_decl( ret, name, proto, args, dfl ) \ 208 ret __weak_impl( name ) proto __attribute__ (( weak )); \ 209 static inline ret name proto { \ 210 if ( __weak_impl( name ) ) \ 211 return __weak_impl( name ) args; \ 212 return dfl; \ 213 } 214 215 #endif 216 /** @} */ 217 218 /** @defgroup dbg Debugging infrastructure 219 * @{ 220 */ 221 #ifndef ASSEMBLY 222 223 /** @def DBG 224 * 225 * Print a debugging message. 226 * 227 * The debug level is set at build time by specifying the @c DEBUG= 228 * parameter on the @c make command line. For example, to enable 229 * debugging for the PCI bus functions (in pci.c) in a @c .dsk image 230 * for the @c rtl8139 card, you could use the command line 231 * 232 * @code 233 * 234 * make bin/rtl8139.dsk DEBUG=pci 235 * 236 * @endcode 237 * 238 * This will enable the debugging statements (DBG()) in pci.c. If 239 * debugging is not enabled, DBG() statements will be ignored. 240 * 241 * You can enable debugging in several objects simultaneously by 242 * separating them with commas, as in 243 * 244 * @code 245 * 246 * make bin/rtl8139.dsk DEBUG=pci,buffer,heap 247 * 248 * @endcode 249 * 250 * You can increase the debugging level for an object by specifying it 251 * with @c :N, where @c N is the level, as in 252 * 253 * @code 254 * 255 * make bin/rtl8139.dsk DEBUG=pci,buffer:2,heap 256 * 257 * @endcode 258 * 259 * which would enable debugging for the PCI, buffer-handling and 260 * heap-allocation code, with the buffer-handling code at level 2. 261 * 262 */ 263 264 /* 265 * If debug_OBJECT is set to a true value, the macro DBG(...) will 266 * expand to printf(...) when compiling OBJECT, and the symbol 267 * DEBUG_LEVEL will be inserted into the object file. 268 * 269 */ 270 #define DEBUG_SYMBOL PREFIX_OBJECT ( debug_ ) 271 272 /** printf() for debugging 273 * 274 * This function exists so that the DBG() macros can expand to 275 * printf() calls without dragging the printf() prototype into scope. 276 * 277 * As far as the compiler is concerned, dbg_printf() and printf() are 278 * completely unrelated calls; it's only at the assembly stage that 279 * references to the dbg_printf symbol are collapsed into references 280 * to the printf symbol. 281 */ 282 extern int __attribute__ (( format ( printf, 1, 2 ) )) 283 dbg_printf ( const char *fmt, ... ) asm ( "printf" ); 284 285 extern void dbg_autocolourise ( unsigned long id ); 286 extern void dbg_decolourise ( void ); 287 extern void dbg_hex_dump_da ( unsigned long dispaddr, 288 const void *data, unsigned long len ); 289 290 #if DEBUG_SYMBOL 291 #define DBGLVL_MAX DEBUG_SYMBOL 292 #else 293 #define DBGLVL_MAX 0 294 #endif 295 296 /* Allow for selective disabling of enabled debug levels */ 297 #if DBGLVL_MAX 298 int __debug_disable; 299 #define DBGLVL ( DBGLVL_MAX & ~__debug_disable ) 300 #define DBG_DISABLE( level ) do { \ 301 __debug_disable |= ( (level) & DBGLVL_MAX ); \ 302 } while ( 0 ) 303 #define DBG_ENABLE( level ) do { \ 304 __debug_disable &= ~( (level) & DBGLVL_MAX ); \ 305 } while ( 0 ) 306 #else 307 #define DBGLVL 0 308 #define DBG_DISABLE( level ) do { } while ( 0 ) 309 #define DBG_ENABLE( level ) do { } while ( 0 ) 310 #endif 311 312 #define DBGLVL_LOG 1 313 #define DBG_LOG ( DBGLVL & DBGLVL_LOG ) 314 #define DBGLVL_EXTRA 2 315 #define DBG_EXTRA ( DBGLVL & DBGLVL_EXTRA ) 316 #define DBGLVL_PROFILE 4 317 #define DBG_PROFILE ( DBGLVL & DBGLVL_PROFILE ) 318 #define DBGLVL_IO 8 319 #define DBG_IO ( DBGLVL & DBGLVL_IO ) 320 321 /** 322 * Print debugging message if we are at a certain debug level 323 * 324 * @v level Debug level 325 * @v ... printf() argument list 326 */ 327 #define DBG_IF( level, ... ) do { \ 328 if ( DBG_ ## level ) { \ 329 dbg_printf ( __VA_ARGS__ ); \ 330 } \ 331 } while ( 0 ) 332 333 /** 334 * Print a hex dump if we are at a certain debug level 335 * 336 * @v level Debug level 337 * @v dispaddr Display address 338 * @v data Data to print 339 * @v len Length of data 340 */ 341 #define DBG_HDA_IF( level, dispaddr, data, len ) do { \ 342 if ( DBG_ ## level ) { \ 343 union { \ 344 unsigned long ul; \ 345 typeof ( dispaddr ) raw; \ 346 } da; \ 347 da.raw = dispaddr; \ 348 dbg_hex_dump_da ( da.ul, data, len ); \ 349 } \ 350 } while ( 0 ) 351 352 /** 353 * Print a hex dump if we are at a certain debug level 354 * 355 * @v level Debug level 356 * @v data Data to print 357 * @v len Length of data 358 */ 359 #define DBG_HD_IF( level, data, len ) do { \ 360 const void *_data = data; \ 361 DBG_HDA_IF ( level, _data, _data, len ); \ 362 } while ( 0 ) 363 364 /** 365 * Select colour for debug messages if we are at a certain debug level 366 * 367 * @v level Debug level 368 * @v id Message stream ID 369 */ 370 #define DBG_AC_IF( level, id ) do { \ 371 if ( DBG_ ## level ) { \ 372 union { \ 373 unsigned long ul; \ 374 typeof ( id ) raw; \ 375 } dbg_stream; \ 376 dbg_stream.raw = id; \ 377 dbg_autocolourise ( dbg_stream.ul ); \ 378 } \ 379 } while ( 0 ) 380 381 /** 382 * Revert colour for debug messages if we are at a certain debug level 383 * 384 * @v level Debug level 385 */ 386 #define DBG_DC_IF( level ) do { \ 387 if ( DBG_ ## level ) { \ 388 dbg_decolourise(); \ 389 } \ 390 } while ( 0 ) 391 392 /* Autocolourising versions of the DBGxxx_IF() macros */ 393 394 #define DBGC_IF( level, id, ... ) do { \ 395 DBG_AC_IF ( level, id ); \ 396 DBG_IF ( level, __VA_ARGS__ ); \ 397 DBG_DC_IF ( level ); \ 398 } while ( 0 ) 399 400 #define DBGC_HDA_IF( level, id, ... ) do { \ 401 DBG_AC_IF ( level, id ); \ 402 DBG_HDA_IF ( level, __VA_ARGS__ ); \ 403 DBG_DC_IF ( level ); \ 404 } while ( 0 ) 405 406 #define DBGC_HD_IF( level, id, ... ) do { \ 407 DBG_AC_IF ( level, id ); \ 408 DBG_HD_IF ( level, __VA_ARGS__ ); \ 409 DBG_DC_IF ( level ); \ 410 } while ( 0 ) 411 412 /* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( LOG, ... )*/ 413 414 #define DBG( ... ) DBG_IF ( LOG, __VA_ARGS__ ) 415 #define DBG_HDA( ... ) DBG_HDA_IF ( LOG, __VA_ARGS__ ) 416 #define DBG_HD( ... ) DBG_HD_IF ( LOG, __VA_ARGS__ ) 417 #define DBGC( ... ) DBGC_IF ( LOG, __VA_ARGS__ ) 418 #define DBGC_HDA( ... ) DBGC_HDA_IF ( LOG, __VA_ARGS__ ) 419 #define DBGC_HD( ... ) DBGC_HD_IF ( LOG, __VA_ARGS__ ) 420 421 /* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( EXTRA, ... )*/ 422 423 #define DBG2( ... ) DBG_IF ( EXTRA, __VA_ARGS__ ) 424 #define DBG2_HDA( ... ) DBG_HDA_IF ( EXTRA, __VA_ARGS__ ) 425 #define DBG2_HD( ... ) DBG_HD_IF ( EXTRA, __VA_ARGS__ ) 426 #define DBGC2( ... ) DBGC_IF ( EXTRA, __VA_ARGS__ ) 427 #define DBGC2_HDA( ... ) DBGC_HDA_IF ( EXTRA, __VA_ARGS__ ) 428 #define DBGC2_HD( ... ) DBGC_HD_IF ( EXTRA, __VA_ARGS__ ) 429 430 /* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( PROFILE, ... )*/ 431 432 #define DBGP( ... ) DBG_IF ( PROFILE, __VA_ARGS__ ) 433 #define DBGP_HDA( ... ) DBG_HDA_IF ( PROFILE, __VA_ARGS__ ) 434 #define DBGP_HD( ... ) DBG_HD_IF ( PROFILE, __VA_ARGS__ ) 435 #define DBGCP( ... ) DBGC_IF ( PROFILE, __VA_ARGS__ ) 436 #define DBGCP_HDA( ... ) DBGC_HDA_IF ( PROFILE, __VA_ARGS__ ) 437 #define DBGCP_HD( ... ) DBGC_HD_IF ( PROFILE, __VA_ARGS__ ) 438 439 /* Versions of the DBGxxx_IF() macros that imply DBGxxx_IF( IO, ... )*/ 440 441 #define DBGIO( ... ) DBG_IF ( IO, __VA_ARGS__ ) 442 #define DBGIO_HDA( ... ) DBG_HDA_IF ( IO, __VA_ARGS__ ) 443 #define DBGIO_HD( ... ) DBG_HD_IF ( IO, __VA_ARGS__ ) 444 #define DBGCIO( ... ) DBGC_IF ( IO, __VA_ARGS__ ) 445 #define DBGCIO_HDA( ... ) DBGC_HDA_IF ( IO, __VA_ARGS__ ) 446 #define DBGCIO_HD( ... ) DBGC_HD_IF ( IO, __VA_ARGS__ ) 447 448 449 #if DEBUG_SYMBOL == 0 450 #define NDEBUG 451 #endif 452 453 #endif /* ASSEMBLY */ 454 /** @} */ 455 456 /** @defgroup attrs Miscellaneous attributes 457 * @{ 458 */ 459 #ifndef ASSEMBLY 460 461 /** Declare a data structure as packed. */ 462 #define PACKED __attribute__ (( packed )) 463 464 /** Declare a variable or data structure as unused. */ 465 #define __unused __attribute__ (( unused )) 466 467 /** 468 * Declare a function as pure - i.e. without side effects 469 */ 470 #define __pure __attribute__ (( pure )) 471 472 /** 473 * Declare a function as const - i.e. it does not access global memory 474 * (including dereferencing pointers passed to it) at all. 475 * Must also not call any non-const functions. 476 */ 477 #define __const __attribute__ (( const )) 478 479 /** 480 * Declare a function's pointer parameters as non-null - i.e. force 481 * compiler to check pointers at compile time and enable possible 482 * optimizations based on that fact 483 */ 484 #define __nonnull __attribute__ (( nonnull )) 485 486 /** 487 * Declare a pointer returned by a function as a unique memory address 488 * as returned by malloc-type functions. 489 */ 490 #define __malloc __attribute__ (( malloc )) 491 492 /** 493 * Declare a function as used. 494 * 495 * Necessary only if the function is called only from assembler code. 496 */ 497 #define __used __attribute__ (( used )) 498 499 /** Declare a data structure to be aligned with 16-byte alignment */ 500 #define __aligned __attribute__ (( aligned ( 16 ) )) 501 502 /** Declare a function to be always inline */ 503 #define __always_inline __attribute__ (( always_inline )) 504 505 /** 506 * Shared data. 507 * 508 * To save space in the binary when multiple-driver images are 509 * compiled, uninitialised data areas can be shared between drivers. 510 * This will typically be used to share statically-allocated receive 511 * and transmit buffers between drivers. 512 * 513 * Use as e.g. 514 * 515 * @code 516 * 517 * struct { 518 * char rx_buf[NUM_RX_BUF][RX_BUF_SIZE]; 519 * char tx_buf[TX_BUF_SIZE]; 520 * } my_static_data __shared; 521 * 522 * @endcode 523 * 524 */ 525 #define __shared __asm__ ( "_shared_bss" ) __aligned 526 527 #endif /* ASSEMBLY */ 528 /** @} */ 529 530 /** 531 * Optimisation barrier 532 */ 533 #ifndef ASSEMBLY 534 #define barrier() __asm__ __volatile__ ( "" : : : "memory" ) 535 #endif /* ASSEMBLY */ 536 537 /** 538 * @defgroup licences Licence declarations 539 * 540 * For reasons that are partly historical, various different files 541 * within the gPXE codebase have differing licences. 542 * 543 * @{ 544 */ 545 546 /** Declare a file as being in the public domain 547 * 548 * This licence declaration is applicable when a file states itself to 549 * be in the public domain. 550 */ 551 #define FILE_LICENCE_PUBLIC_DOMAIN \ 552 PROVIDE_SYMBOL ( __licence_public_domain ) 553 554 /** Declare a file as being under version 2 (or later) of the GNU GPL 555 * 556 * This licence declaration is applicable when a file states itself to 557 * be licensed under the GNU GPL; "either version 2 of the License, or 558 * (at your option) any later version". 559 */ 560 #define FILE_LICENCE_GPL2_OR_LATER \ 561 PROVIDE_SYMBOL ( __licence_gpl2_or_later ) 562 563 /** Declare a file as being under version 2 of the GNU GPL 564 * 565 * This licence declaration is applicable when a file states itself to 566 * be licensed under version 2 of the GPL, and does not include the 567 * "or, at your option, any later version" clause. 568 */ 569 #define FILE_LICENCE_GPL2_ONLY \ 570 PROVIDE_SYMBOL ( __licence_gpl2_only ) 571 572 /** Declare a file as being under any version of the GNU GPL 573 * 574 * This licence declaration is applicable when a file states itself to 575 * be licensed under the GPL, but does not specify a version. 576 * 577 * According to section 9 of the GPLv2, "If the Program does not 578 * specify a version number of this License, you may choose any 579 * version ever published by the Free Software Foundation". 580 */ 581 #define FILE_LICENCE_GPL_ANY \ 582 PROVIDE_SYMBOL ( __licence_gpl_any ) 583 584 /** Declare a file as being under the three-clause BSD licence 585 * 586 * This licence declaration is applicable when a file states itself to 587 * be licensed under terms allowing redistribution in source and 588 * binary forms (with or without modification) provided that: 589 * 590 * redistributions of source code retain the copyright notice, 591 * list of conditions and any attached disclaimers 592 * 593 * redistributions in binary form reproduce the copyright notice, 594 * list of conditions and any attached disclaimers in the 595 * documentation and/or other materials provided with the 596 * distribution 597 * 598 * the name of the author is not used to endorse or promote 599 * products derived from the software without specific prior 600 * written permission 601 * 602 * It is not necessary for the file to explicitly state that it is 603 * under a "BSD" licence; only that the licensing terms be 604 * functionally equivalent to the standard three-clause BSD licence. 605 */ 606 #define FILE_LICENCE_BSD3 \ 607 PROVIDE_SYMBOL ( __licence_bsd3 ) 608 609 /** Declare a file as being under the two-clause BSD licence 610 * 611 * This licence declaration is applicable when a file states itself to 612 * be licensed under terms allowing redistribution in source and 613 * binary forms (with or without modification) provided that: 614 * 615 * redistributions of source code retain the copyright notice, 616 * list of conditions and any attached disclaimers 617 * 618 * redistributions in binary form reproduce the copyright notice, 619 * list of conditions and any attached disclaimers in the 620 * documentation and/or other materials provided with the 621 * distribution 622 * 623 * It is not necessary for the file to explicitly state that it is 624 * under a "BSD" licence; only that the licensing terms be 625 * functionally equivalent to the standard two-clause BSD licence. 626 */ 627 #define FILE_LICENCE_BSD2 \ 628 PROVIDE_SYMBOL ( __licence_bsd2 ) 629 630 /** Declare a file as being under the one-clause MIT-style licence 631 * 632 * This licence declaration is applicable when a file states itself to 633 * be licensed under terms allowing redistribution for any purpose 634 * with or without fee, provided that the copyright notice and 635 * permission notice appear in all copies. 636 */ 637 #define FILE_LICENCE_MIT \ 638 PROVIDE_SYMBOL ( __licence_mit ) 639 640 /** Declare a particular licence as applying to a file */ 641 #define FILE_LICENCE( _licence ) FILE_LICENCE_ ## _licence 642 643 /** @} */ 644 645 /* This file itself is under GPLv2-or-later */ 646 FILE_LICENCE ( GPL2_OR_LATER ); 647 648 #include <bits/compiler.h> 649 650 #endif /* COMPILER_H */ 651