From 1c67623e37dada045e9b5d1f5e19b414cc79c3e3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 10 Mar 2009 17:50:01 +0000 Subject: [build] Enable building with the Intel C compiler (icc) --- src/include/compiler.h | 3 +- src/include/gpxe/efi/efi.h | 7 +++- src/include/gpxe/tables.h | 95 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 94 insertions(+), 11 deletions(-) (limited to 'src/include') diff --git a/src/include/compiler.h b/src/include/compiler.h index 889c24047..be3ce46fc 100644 --- a/src/include/compiler.h +++ b/src/include/compiler.h @@ -212,7 +212,8 @@ int __debug_disable; * @v len Length of data */ #define DBG_HD_IF( level, data, len ) do { \ - DBG_HDA_IF ( level, data, data, len ); \ + const void *_data = data; \ + DBG_HDA_IF ( level, _data, _data, len ); \ } while ( 0 ) /** diff --git a/src/include/gpxe/efi/efi.h b/src/include/gpxe/efi/efi.h index 1f5b88563..a71a29e27 100644 --- a/src/include/gpxe/efi/efi.h +++ b/src/include/gpxe/efi/efi.h @@ -31,6 +31,11 @@ /* EFI headers rudely redefine NULL */ #undef NULL +/* EFI headers expect ICC to define __GNUC__ */ +#if defined ( __ICC ) && ! defined ( __GNUC__ ) +#define __GNUC__ 1 +#endif + /* Include the top-level EFI header files */ #include #include @@ -69,7 +74,7 @@ struct efi_protocol { struct efi_protocol __ ## _protocol __efi_protocol = { \ .u.guid = _protocol ## _GUID, \ .protocol = ( ( void ** ) ( void * ) \ - ( ( (_ptr) == ( ( _protocol ** ) NULL ) ) ? \ + ( ( (_ptr) == ( ( _protocol ** ) (_ptr) ) ) ? \ (_ptr) : (_ptr) ) ), \ } diff --git a/src/include/gpxe/tables.h b/src/include/gpxe/tables.h index a0b6f1137..39b4777f2 100644 --- a/src/include/gpxe/tables.h +++ b/src/include/gpxe/tables.h @@ -234,9 +234,21 @@ * @endcode */ #define __table_entry( table, idx ) \ - __attribute__ (( __section__ ( __table_section ( table, idx ) ) \ + __attribute__ (( __section__ ( __table_section ( table, idx ) ),\ __aligned__ ( __table_alignment ( table ) ) )) +/** + * Get start of linker table entries + * + * @v table Linker table + * @v idx Sub-table index + * @ret entries Start of entries + */ +#define __table_entries( table, idx ) ( { \ + static __table_type ( table ) __table_entries[0] \ + __table_entry ( table, idx ); \ + __table_entries; } ) + /** * Get start of linker table * @@ -253,10 +265,7 @@ * * @endcode */ -#define table_start( table ) ( { \ - static __table_type ( table ) __table_start[0] \ - __table_entry ( table, 00 ); \ - __table_start; } ) +#define table_start( table ) __table_entries ( table, 00 ) /** * Get end of linker table @@ -274,10 +283,7 @@ * * @endcode */ -#define table_end( table ) ( { \ - static __table_type ( table ) __table_end[0] \ - __table_entry ( table, 99 ); \ - __table_end; } ) +#define table_end( table ) __table_entries ( table, 99 ) /** * Get number of entries in linker table @@ -352,4 +358,75 @@ pointer >= table_start ( table ) ; \ pointer-- ) +/****************************************************************************** + * + * Intel's C compiler chokes on several of the constructs used in this + * file. The workarounds are ugly, so we use them only for an icc + * build. + * + */ +#define ICC_ALIGN_HACK_FACTOR 128 +#ifdef __ICC + +/* + * icc miscompiles zero-length arrays by inserting padding to a length + * of two array elements. We therefore have to generate the + * __table_entries() symbols by hand in asm. + * + */ +#undef __table_entries +#define __table_entries( table, idx ) ( { \ + extern __table_type ( table ) \ + __table_temp_sym ( idx, __LINE__ ) [] \ + __table_entry ( table, idx ) \ + asm ( __table_entries_sym ( table, idx ) ); \ + __asm__ ( ".ifndef %c0\n\t" \ + ".section " __table_section ( table, idx ) "\n\t" \ + ".align %c1\n\t" \ + "\n%c0:\n\t" \ + ".previous\n\t" \ + ".endif\n\t" \ + : : "i" ( __table_temp_sym ( idx, __LINE__ ) ), \ + "i" ( __table_alignment ( table ) ) ); \ + __table_temp_sym ( idx, __LINE__ ); } ) +#define __table_entries_sym( table, idx ) \ + "__tbl_" __table_name ( table ) "_" #idx +#define __table_temp_sym( a, b ) \ + ___table_temp_sym( __table_, a, _, b ) +#define ___table_temp_sym( a, b, c, d ) a ## b ## c ## d + +/* + * icc ignores __attribute__ (( aligned (x) )) when it is used to + * decrease the compiler's default choice of alignment (which may be + * higher than the alignment actually required by the structure). We + * work around this by forcing the alignment to a large multiple of + * the required value (so that we are never attempting to decrease the + * default alignment) and then postprocessing the object file to + * reduce the alignment back down to the "real" value. + * + */ +#undef __table_alignment +#define __table_alignment( table ) \ + ( ICC_ALIGN_HACK_FACTOR * __alignof__ ( __table_type ( table ) ) ) + +/* + * Because of the alignment hack, we must ensure that the compiler + * never tries to place multiple objects within the same section, + * otherwise the assembler will insert padding to the (incorrect) + * alignment boundary. Do this by appending the line number to table + * section names. + * + * Note that we don't need to worry about padding between array + * elements, since the alignment is declared on the variable (i.e. the + * whole array) rather than on the type (i.e. on all individual array + * elements). + */ +#undef __table_section +#define __table_section( table, idx ) \ + ".tbl." __table_name ( table ) "." __table_str ( idx ) \ + "." __table_xstr ( __LINE__ ) +#define __table_xstr( x ) __table_str ( x ) + +#endif /* __ICC */ + #endif /* _GPXE_TABLES_H */ -- cgit v1.2.3-55-g7522