Home | History | Annotate | Download | only in Include
      1 /*++
      2 
      3 Copyright (c) 2004, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   EfiStdArg.h
     15 
     16 Abstract:
     17 
     18   Support for variable length argument lists using the ANSI standard.
     19 
     20   Since we are using the ANSI standard we used the standard nameing and
     21   did not folow the coding convention
     22 
     23   VA_LIST  - typedef for argument list.
     24   VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use.
     25   VA_END (VA_LIST Marker) - Clear Marker
     26   VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argumnet from
     27     the ... list. You must know the size and pass it in this macro.
     28 
     29   example:
     30 
     31   UINTN
     32   ExampleVarArg (
     33     IN UINTN  NumberOfArgs,
     34     ...
     35     )
     36   {
     37     VA_LIST Marker;
     38     UINTN   Index;
     39     UINTN   Result;
     40 
     41     //
     42     // Initialize the Marker
     43     //
     44     VA_START (Marker, NumberOfArgs);
     45     for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) {
     46       //
     47       // The ... list is a series of UINTN values, so average them up.
     48       //
     49       Result += VA_ARG (Marker, UINTN);
     50     }
     51 
     52     VA_END (Marker);
     53     return Result
     54   }
     55 
     56 --*/
     57 
     58 #ifndef _EFISTDARG_H_
     59 #define _EFISTDARG_H_
     60 
     61 /**
     62   Return the size of argument that has been aligned to sizeof (UINTN).
     63 
     64   @param  n    The parameter size to be aligned.
     65 
     66   @return The aligned size.
     67 **/
     68 #define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))
     69 
     70 #if defined(__CC_ARM)
     71 //
     72 // RVCT ARM variable argument list support.
     73 //
     74 
     75 ///
     76 /// Variable used to traverse the list of arguments. This type can vary by
     77 /// implementation and could be an array or structure.
     78 ///
     79 #ifdef __APCS_ADSABI
     80   typedef int         *va_list[1];
     81   #define VA_LIST     va_list
     82 #else
     83   typedef struct __va_list { void *__ap; } va_list;
     84   #define VA_LIST                          va_list
     85 #endif
     86 
     87 #define VA_START(Marker, Parameter)   __va_start(Marker, Parameter)
     88 
     89 #define VA_ARG(Marker, TYPE)          __va_arg(Marker, TYPE)
     90 
     91 #define VA_END(Marker)                ((void)0)
     92 
     93 #define VA_COPY(Dest, Start)          __va_copy (Dest, Start)
     94 
     95 #elif defined(__GNUC__)
     96 
     97 #if defined(MDE_CPU_X64) && !defined(NO_MSABI_VA_FUNCS)
     98 //
     99 // X64 only. Use MS ABI version of GCC built-in macros for variable argument lists.
    100 //
    101 ///
    102 /// Both GCC and LLVM 3.8 for X64 support new variable argument intrinsics for Microsoft ABI
    103 ///
    104 
    105 ///
    106 /// Variable used to traverse the list of arguments. This type can vary by
    107 /// implementation and could be an array or structure.
    108 ///
    109 typedef __builtin_ms_va_list VA_LIST;
    110 
    111 #define VA_START(Marker, Parameter)  __builtin_ms_va_start (Marker, Parameter)
    112 
    113 #define VA_ARG(Marker, TYPE)         ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
    114 
    115 #define VA_END(Marker)               __builtin_ms_va_end (Marker)
    116 
    117 #define VA_COPY(Dest, Start)         __builtin_ms_va_copy (Dest, Start)
    118 
    119 #else
    120 //
    121 // Use GCC built-in macros for variable argument lists.
    122 //
    123 
    124 ///
    125 /// Variable used to traverse the list of arguments. This type can vary by
    126 /// implementation and could be an array or structure.
    127 ///
    128 typedef __builtin_va_list VA_LIST;
    129 
    130 #define VA_START(Marker, Parameter)  __builtin_va_start (Marker, Parameter)
    131 
    132 #define VA_ARG(Marker, TYPE)         ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
    133 
    134 #define VA_END(Marker)               __builtin_va_end (Marker)
    135 
    136 #define VA_COPY(Dest, Start)         __builtin_va_copy (Dest, Start)
    137 
    138 #endif
    139 
    140 #else
    141 
    142 #ifndef VA_START
    143 
    144 ///
    145 /// Variable used to traverse the list of arguments. This type can vary by
    146 /// implementation and could be an array or structure.
    147 ///
    148 typedef CHAR8 *VA_LIST;
    149 
    150 /**
    151   Retrieves a pointer to the beginning of a variable argument list, based on
    152   the name of the parameter that immediately precedes the variable argument list.
    153 
    154   This function initializes Marker to point to the beginning of the variable
    155   argument list that immediately follows Parameter.  The method for computing the
    156   pointer to the next argument in the argument list is CPU-specific following the
    157   EFIAPI ABI.
    158 
    159   @param   Marker       The VA_LIST used to traverse the list of arguments.
    160   @param   Parameter    The name of the parameter that immediately precedes
    161                         the variable argument list.
    162 
    163   @return  A pointer to the beginning of a variable argument list.
    164 
    165 **/
    166 #define VA_START(Marker, Parameter) (Marker = (VA_LIST) ((UINTN) & (Parameter) + _INT_SIZE_OF (Parameter)))
    167 
    168 /**
    169   Returns an argument of a specified type from a variable argument list and updates
    170   the pointer to the variable argument list to point to the next argument.
    171 
    172   This function returns an argument of the type specified by TYPE from the beginning
    173   of the variable argument list specified by Marker.  Marker is then updated to point
    174   to the next argument in the variable argument list.  The method for computing the
    175   pointer to the next argument in the argument list is CPU-specific following the EFIAPI ABI.
    176 
    177   @param   Marker   VA_LIST used to traverse the list of arguments.
    178   @param   TYPE     The type of argument to retrieve from the beginning
    179                     of the variable argument list.
    180 
    181   @return  An argument of the type specified by TYPE.
    182 
    183 **/
    184 #define VA_ARG(Marker, TYPE)   (*(TYPE *) ((Marker += _INT_SIZE_OF (TYPE)) - _INT_SIZE_OF (TYPE)))
    185 
    186 /**
    187   Terminates the use of a variable argument list.
    188 
    189   This function initializes Marker so it can no longer be used with VA_ARG().
    190   After this macro is used, the only way to access the variable argument list is
    191   by using VA_START() again.
    192 
    193   @param   Marker   VA_LIST used to traverse the list of arguments.
    194 
    195 **/
    196 #define VA_END(Marker)      (Marker = (VA_LIST) 0)
    197 
    198 #define VA_COPY(dest, src) ((void)((dest) = (src)))
    199 
    200 #endif
    201 
    202 #endif
    203 
    204 #endif
    205