Skip to content

CompilerAttributes

Jeff Squyres edited this page Sep 2, 2014 · 3 revisions

Summary

The compiler attributes allow the developer to specify more context regarding a variable, structure definition or function. With these hints, the compiler then is able to do better error checking and give warnings or to better optimize the variable access, function call, or get rid of function calls altogether.

Current Status

The compiler's support for the following attributes is being checked for in during configure:

  • optimization (always_inline, const, pure, malloc, may_alias, noreturn)
  • data layout (align, packed)
  • interface definition, API (deprecated, visibility, weak alias)
  • hint for code analysis and debugging (format, nonnull, sentinel, unused, warn_unused_result)

Depending on the availability, the attribute's macros are defined in opal/include/opal_config_bottom.h.

Developers Howto

The developper may detect occasions, where it is worthwhile to specify hints to the compiler, such as aliasing information or where heavily used functions shouldbe inlined. Functions and Variables should be chosen carefully, as some of these hints may not be correctly checked for by the compiler itself; some hints may also reduce performance, e.g. if always_inline is specified on a large function, which may blow the instruction cache, when referenced in many call-sites.

The following short description is just a summary of the available attributes; please see the online gcc-manual, specifically the attributes on functions, attributes on variables and attributes on types for a thorough description.

Optimization Attributes

  • always_inline

    This attribute forces the corresponding function to always be inlined, no matter what the compiler's internal heuristics say. Example:

int square (int arg) __opal_attribute_always_inline__;
  • cold

    See attribute hot below. One example may be:

*_opal_attribute_cold_* int MPI_Finalize(void)
  • const

    The corresponding function does not use any other value, other than their arguments and have no side effects, except their return value. Functions may particularly not call any global memory. Same example as above.

  • hot

    Mark the function to be placed into the hot section upon linking (requires gcc > 4.2). This requires the compile options -freorder-functions. One example may be:

*_opal_attribute_hot_* int MPI_Wait(MPI_Request * request, MPI_Status *status)
  • pure

    The function only depends on its arguments and (non-volatile!) global memory. Writing into global memory nevertheless is not allowed. Same example as above.

  • malloc

    To do better alias analysis, one may hint to the compiler, that this function is allocating new memory, therefore this memory cannot alias any other pointer. Good examples are:

char * strdup (const char * string) __opal_attribute_malloc__; 

or

void *mca_mpool_base_alloc(size_t size, ompi_info_t *info) __opal_attribute_malloc__;
  • may_alias

    In contrast to the previously mention attribute, this attribute may be specified on types, to disallow alias-analysis; using a pointer with such a type will assume aliasing. Good example may be found in gcc online manual on type attributes.

  • noreturn

    Specify that this function will never return, enabling optimizations and dead-code removal at the call-site.

Data Layout Attributes

  • align

    Specify the alignment of the data; as this attribute has two forms, either with argument, or without an argument (for maximum available alignment for the type in question), there exist two attributes:

struct {
    char * name;
    int initialized __opal_attribute_aligned__(8);
}

and

struct {
     char * name;
     int initialized __opal_attribute_aligned_max__;
}
  • packed

    To overcome alignment and padding, one may specify the packed attribute:

struct *_opal_attribute_packed_* my_struct {
     char * name;
     int initialized;
}

Note that not all compilers support these features, so they should not be used to overcome alignment and padding rules in heterogeneous situations.

Interface Definition and API Attributes

  • deprecated

    In case an interface changes, one may warn users of the soon-to-be-deleted functions or global variables.

  • visibility

    To reduce the amount of exported symbols, one may reduce the visibility of internal functions, as described in the Visbility-section.

  • weak alias

    Just as #pragma weak, this enables weak aliasing of function names to other functions, as used in Open MPI's profiling interface definition.

Code Analysis and Debugging Attributes

  • format

    This attribute specifies the type and parameter to be used for argument checking as is done on printf and alike. It takes two numeric arguments: the first indicates which argument is the "format" argument (i.e., the string that basically indicates which vararg types should follow) and the second is the number of the first variadic argument. Example:

void opal_output(int id, const char *format, ...) __opal_attribute_format__(__printf__, 2, 3);
  • nonnull

    This attribute specifies, that a certain argument in the function call must not be NULL. This allows easy checking at compile-time and hopefully less checking in the function internally. Example:

int MPI_Comm_group(MPI_Comm comm, MPI_Group *group) __opal_attribute_nonnull_all__;

Additionally, you can check for specific arguments that should be non-null. Example:

void some_function(int a, char *b)__opal_attribute_nonnull__(2);
  • sentinel

    Specify, that the last argument to a variadic function must be NULL; errors in doing so will result in warnings, when using -Wformat. As an example (which may also take __opal_attribute_malloc__):

char *opal_os_path(bool relative, ...) __opal_attribute_sentinel__;
  • unused

    When compiling with -Wunused (or -Wunused-function for that matter), one often gets a myriad of unnecessary warnings on unused arguments. This is due to the system of MCAs, where a particular implementation does not require the argument. To discard such warnings, one may specify this attribute. Example:

static inline int32_t ompi_ddt_is_acceptable_for_one_sided(
         const ompi_datatype_t* type *_opal_attribute_unused_* )
      { return true; }
  • warn_unused_result

    Similar to unused, you can have the compiler warn you if the return of a function is ignored. Although we should technically never ignore the return of a function, it's even more important when the function returns something that should be freed (for example). Example:

char *opal_argv_join(char **argv, int delimiter) 
        *_opal_attribute_malloc_* __opal_attribute_nonnull__(1) __opal_attribute_warn_unused_result__;
Clone this wiki locally