All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
attributes.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef ARCH_ATTRIBUTES_H
25 #define ARCH_ATTRIBUTES_H
26 
32 
33 #include "pxr/pxr.h"
34 #include "pxr/base/arch/export.h"
35 
36 PXR_NAMESPACE_OPEN_SCOPE
37 
38 #if defined(doxygen)
39 
51 # define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
52 
65 # define ARCH_SCANF_FUNCTION(_fmt, _firstArg)
66 
75 # define ARCH_NOINLINE
76 
89 # define ARCH_UNUSED_ARG
90 
104 # define ARCH_UNUSED_FUNCTION
105 
124 # define ARCH_USED_FUNCTION
125 
143 # define ARCH_CONSTRUCTOR(_name, _priority, ...)
144 
162 # define ARCH_DESTRUCTOR(_name, _priority, ...)
163 
164 #elif defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG)
165 
166 # define ARCH_PRINTF_FUNCTION(_fmt, _firstArg) \
167  __attribute__((format(printf, _fmt, _firstArg)))
168 # define ARCH_SCANF_FUNCTION(_fmt, _firstArg) \
169  __attribute__((format(scanf, _fmt, _firstArg)))
170 # define ARCH_NOINLINE __attribute__((noinline))
171 # define ARCH_UNUSED_ARG __attribute__ ((unused))
172 # define ARCH_UNUSED_FUNCTION __attribute__((unused))
173 # define ARCH_USED_FUNCTION __attribute__((used))
174 
175 #elif defined(ARCH_COMPILER_MSVC)
176 
177 # define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
178 # define ARCH_SCANF_FUNCTION(_fmt, _firstArg)
179 # define ARCH_NOINLINE // __declspec(noinline)
180 # define ARCH_UNUSED_ARG
181 # define ARCH_UNUSED_FUNCTION
182 # define ARCH_USED_FUNCTION
183 
184 #else
185 
186 // Leave macros undefined so we'll fail to build on a new system/compiler
187 // rather than fail mysteriously at runtime.
188 
189 #endif
190 
191 // Helper to do on-demand static initialziation. We need to insert per-library
192 // static initializers if the ARCH_CONSTRUCTOR macros are used, etc, but we
193 // don't want that to happen otherwise. This mechanism makes that possible. It
194 // works by creating a class template (Arch_PerLibInit) that has hidden
195 // visibility and a static member of its template parameter (StaticInit). In
196 // its constructor, it "uses" its static member 'init', in order to ensure it
197 // gets instantiated. Since it's a static member, it gets initialized only if
198 // it's instantiated. This lets us have macros like ARCH_CONSTRUCTOR() that
199 // require a static initializer, but to only emit that static initializer in
200 // translation units that actually invoke the macro. Clients typically do this
201 // by way of the _ARCH_ENSURE_PER_LIB_INIT macro. This is tested on all current
202 // supported compilers (clang, gcc, msvc). The hidden visibility is required to
203 // ensure that each library gets its own initialization. Without it, on Linux,
204 // there would be exactly *one* initialization no matter how many libraries are
205 // loaded.
206 template <class StaticInit>
207 struct ARCH_HIDDEN Arch_PerLibInit {
208  Arch_PerLibInit() { /* "use" of init here forces instantiation */
209  (void)init; }
210 private:
211  static StaticInit init;
212 };
213 template <class StaticInit>
214 StaticInit Arch_PerLibInit<StaticInit>::init;
215 
216 #define _ARCH_CAT_NOEXPAND(a, b) a ## b
217 #define _ARCH_CAT(a, b) _ARCH_CAT_NOEXPAND(a, b)
218 #define _ARCH_ENSURE_PER_LIB_INIT(T, prefix) \
219  static Arch_PerLibInit<T> _ARCH_CAT(prefix, __COUNTER__)
220 
221 #if defined(doxygen)
222 
223 // The macros are already defined above in doxygen.
224 
225 #elif defined(ARCH_OS_DARWIN)
226 
227 // Entry for a constructor/destructor in the custom section.
228 struct Arch_ConstructorEntry {
229  typedef void (*Type)(void);
230  Type function;
231  unsigned int version:24; // USD version
232  unsigned int priority:8; // Priority of function
233 };
234 
235 // Emit a Arch_ConstructorEntry in the __Data,pxrctor section.
236 # define ARCH_CONSTRUCTOR(_name, _priority, ...) \
237  static void _name(__VA_ARGS__); \
238  static const Arch_ConstructorEntry _ARCH_CAT_NOEXPAND(arch_ctor_, _name) \
239  __attribute__((used, section("__DATA,pxrctor"))) = { \
240  reinterpret_cast<Arch_ConstructorEntry::Type>(&_name), \
241  0u, \
242  _priority \
243  }; \
244  static void _name(__VA_ARGS__)
245 
246 // Emit a Arch_ConstructorEntry in the __Data,pxrdtor section.
247 # define ARCH_DESTRUCTOR(_name, _priority, ...) \
248  static void _name(__VA_ARGS__); \
249  static const Arch_ConstructorEntry _ARCH_CAT_NOEXPAND(arch_dtor_, _name) \
250  __attribute__((used, section("__DATA,pxrdtor"))) = { \
251  reinterpret_cast<Arch_ConstructorEntry::Type>(&_name), \
252  0u, \
253  _priority \
254  }; \
255  static void _name(__VA_ARGS__)
256 
257 #elif defined(ARCH_OS_WINDOWS)
258 
259 # include "pxr/base/arch/api.h"
260 
261 // Entry for a constructor/destructor in the custom section.
262  __declspec(align(16))
263  struct Arch_ConstructorEntry {
264  typedef void (__cdecl *Type)(void);
265  Type function;
266  unsigned int version:24; // USD version
267  unsigned int priority:8; // Priority of function
268  };
269 
270 // Declare the special sections.
271 # pragma section(".pxrctor", read)
272 # pragma section(".pxrdtor", read)
273 
274 // Objects of this type run the ARCH_CONSTRUCTOR and ARCH_DESTRUCTOR functions
275 // for the library containing the object in the c'tor and d'tor, respectively.
276 // Each HMODULE is handled at most once.
277 struct Arch_ConstructorInit {
278  ARCH_API Arch_ConstructorInit();
279  ARCH_API ~Arch_ConstructorInit();
280 };
281 
282 // Emit a Arch_ConstructorEntry in the .pxrctor section. The namespace and
283 // extern are to convince the compiler and linker to leave the object in the
284 // final library/executable instead of stripping it out. In clang/gcc we use
285 // __attribute__((used)) to do that.
286 # define ARCH_CONSTRUCTOR(_name, _priority, ...) \
287  static void _name(__VA_ARGS__); \
288  namespace { \
289  __declspec(allocate(".pxrctor")) \
290  extern const Arch_ConstructorEntry \
291  _ARCH_CAT_NOEXPAND(arch_ctor_, _name) = { \
292  reinterpret_cast<Arch_ConstructorEntry::Type>(&_name), \
293  0u, \
294  _priority \
295  }; \
296  } \
297  _ARCH_ENSURE_PER_LIB_INIT(Arch_ConstructorInit, _archCtorInit); \
298  static void _name(__VA_ARGS__)
299 
300  // Emit a Arch_ConstructorEntry in the .pxrdtor section.
301 # define ARCH_DESTRUCTOR(_name, _priority, ...) \
302  static void _name(__VA_ARGS__); \
303  namespace { \
304  __declspec(allocate(".pxrdtor")) \
305  extern const Arch_ConstructorEntry \
306  _ARCH_CAT_NOEXPAND(arch_dtor_, _name) = { \
307  reinterpret_cast<Arch_ConstructorEntry::Type>(&_name), \
308  0u, \
309  _priority \
310  }; \
311  } \
312  _ARCH_ENSURE_PER_LIB_INIT(Arch_ConstructorInit, _archCtorInit); \
313  static void _name(__VA_ARGS__)
314 
315 #elif defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG)
316 
317 // The used attribute is required to prevent these apparently unused functions
318 // from being removed by the linker.
319 # define ARCH_CONSTRUCTOR(_name, _priority, ...) \
320  __attribute__((used, section(".pxrctor"), constructor((_priority) + 100))) \
321  static void _name(__VA_ARGS__)
322 # define ARCH_DESTRUCTOR(_name, _priority, ...) \
323  __attribute__((used, section(".pxrdtor"), destructor((_priority) + 100))) \
324  static void _name(__VA_ARGS__)
325 
326 #else
327 
328 // Leave macros undefined so we'll fail to build on a new system/compiler
329 // rather than fail mysteriously at runtime.
330 
331 #endif
332 
333 PXR_NAMESPACE_CLOSE_SCOPE
334 
335 #endif // ARCH_ATTRIBUTES_H