Pixar Arch 0.25.8
Loading...
Searching...
No Matches
attributes.h
Go to the documentation of this file.
1// Copyright 2016 Pixar
2//
3// Licensed under the terms set forth in the LICENSE.txt file available at
4// https://openusd.org/license.
5//
6// Modified by Jeremy Retailleau.
7
8#ifndef PXR_ARCH_ATTRIBUTES_H
9#define PXR_ARCH_ATTRIBUTES_H
10
16
17#include "pxr/arch/pxr.h"
18#include "pxr/arch/export.h"
19
20ARCH_NAMESPACE_OPEN_SCOPE
21
22#if defined(doxygen)
23
35# define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
36
49# define ARCH_SCANF_FUNCTION(_fmt, _firstArg)
50
59# define ARCH_NOINLINE
60
73# define ARCH_UNUSED_ARG
74
88# define ARCH_UNUSED_FUNCTION
89
108# define ARCH_USED_FUNCTION
109
123# define ARCH_CONSTRUCTOR(_name, _priority)
124
138# define ARCH_DESTRUCTOR(_name, _priority)
139
146# define ARCH_EMPTY_BASES
147
148#elif defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG)
149
150# define ARCH_PRINTF_FUNCTION(_fmt, _firstArg) \
151 __attribute__((format(printf, _fmt, _firstArg)))
152# define ARCH_SCANF_FUNCTION(_fmt, _firstArg) \
153 __attribute__((format(scanf, _fmt, _firstArg)))
154# define ARCH_NOINLINE __attribute__((noinline))
155# define ARCH_ALWAYS_INLINE __attribute__((always_inline))
156# define ARCH_UNUSED_ARG __attribute__ ((unused))
157# define ARCH_UNUSED_FUNCTION __attribute__((unused))
158# define ARCH_USED_FUNCTION __attribute__((used))
159# define ARCH_EMPTY_BASES
160
161#elif defined(ARCH_COMPILER_MSVC)
162
163# define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
164# define ARCH_SCANF_FUNCTION(_fmt, _firstArg)
165# define ARCH_NOINLINE // __declspec(noinline)
166# define ARCH_ALWAYS_INLINE
167# define ARCH_UNUSED_ARG
168# define ARCH_UNUSED_FUNCTION
169# define ARCH_USED_FUNCTION
170# define ARCH_EMPTY_BASES __declspec(empty_bases)
171
172#else
173
174// Leave macros undefined so we'll fail to build on a new system/compiler
175// rather than fail mysteriously at runtime.
176
177#endif
178
179// Helper to do on-demand static initialization. We need to insert per-library
180// static initializers if the ARCH_CONSTRUCTOR macros are used, etc, but we
181// don't want that to happen otherwise. This mechanism makes that possible. It
182// works by creating a class template (Arch_PerLibInit) that has hidden
183// visibility and a static member of its template parameter (StaticInit). In
184// its constructor, it "uses" its static member 'init', in order to ensure it
185// gets instantiated. Since it's a static member, it gets initialized only if
186// it's instantiated. This lets us have macros like ARCH_CONSTRUCTOR() that
187// require a static initializer, but to only emit that static initializer in
188// translation units that actually invoke the macro. Clients typically do this
189// by way of the _ARCH_ENSURE_PER_LIB_INIT macro. This is tested on all current
190// supported compilers (clang, gcc, msvc). The hidden visibility is required to
191// ensure that each library gets its own initialization. Without it, on Linux,
192// there would be exactly *one* initialization no matter how many libraries are
193// loaded.
194template <class StaticInit>
196 Arch_PerLibInit() { /* "use" of init here forces instantiation */
197 (void)init; }
198private:
199 static StaticInit init;
200};
201template <class StaticInit>
202StaticInit Arch_PerLibInit<StaticInit>::init;
203
204#define _ARCH_CAT_NOEXPAND(a, b) a ## b
205#define _ARCH_CAT(a, b) _ARCH_CAT_NOEXPAND(a, b)
206#define _ARCH_ENSURE_PER_LIB_INIT(T, prefix) \
207 static ARCH_NS::Arch_PerLibInit<T> _ARCH_CAT(prefix, __COUNTER__)
208
209#if defined(doxygen)
210
211// The macros are already defined above in doxygen.
212
213#elif defined(ARCH_OS_DARWIN)
214
215// Entry for a constructor/destructor in the custom section.
216struct Arch_ConstructorEntry {
217 typedef void (*Type)(void);
218 Type function;
219 unsigned int version:24; // USD version
220 unsigned int priority:8; // Priority of function
221};
222
223// Emit a Arch_ConstructorEntry in the __Data,pxrctor section.
224# define ARCH_CONSTRUCTOR(_name, _priority) \
225 static void _name(); \
226 static const ARCH_NS::Arch_ConstructorEntry _ARCH_CAT_NOEXPAND(arch_ctor_, _name) \
227 __attribute__((used, section("__DATA,pxrctor"))) = { \
228 reinterpret_cast<ARCH_NS::Arch_ConstructorEntry::Type>(&_name), \
229 static_cast<unsigned>(ARCH_VERSION), \
230 _priority \
231 }; \
232 static void _name()
233
234// Emit a Arch_ConstructorEntry in the __Data,pxrdtor section.
235# define ARCH_DESTRUCTOR(_name, _priority) \
236 static void _name(); \
237 static const ARCH_NS::Arch_ConstructorEntry _ARCH_CAT_NOEXPAND(arch_dtor_, _name) \
238 __attribute__((used, section("__DATA,pxrdtor"))) = { \
239 reinterpret_cast<ARCH_NS::Arch_ConstructorEntry::Type>(&_name), \
240 static_cast<unsigned>(ARCH_VERSION), \
241 _priority \
242 }; \
243 static void _name()
244
245#elif defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG)
246
247// The used attribute is required to prevent these apparently unused functions
248// from being removed by the linker.
249# define ARCH_CONSTRUCTOR(_name, _priority) \
250 __attribute__((used, section(".pxrctor"), constructor((_priority) + 100))) \
251 static void _name()
252# define ARCH_DESTRUCTOR(_name, _priority) \
253 __attribute__((used, section(".pxrdtor"), destructor((_priority) + 100))) \
254 static void _name()
255
256#elif defined(ARCH_OS_WINDOWS)
257
258# include "./api.h"
259
260// Entry for a constructor/destructor in the custom section.
261 __declspec(align(16))
262 struct Arch_ConstructorEntry {
263 typedef void (__cdecl *Type)(void);
264 Type function;
265 unsigned int version:24; // USD version
266 unsigned int priority:8; // Priority of function
267 };
268
269// Declare the special sections.
270# pragma section(".pxrctor", read)
271# pragma section(".pxrdtor", read)
272
273// Objects of this type run the ARCH_CONSTRUCTOR and ARCH_DESTRUCTOR functions
274// for the library containing the object in the c'tor and d'tor, respectively.
275// Each HMODULE is handled at most once.
276struct Arch_ConstructorInit {
277 ARCH_API Arch_ConstructorInit();
278 ARCH_API ~Arch_ConstructorInit();
279};
280
281// Emit a Arch_ConstructorEntry in the .pxrctor section. The namespace and
282// extern are to convince the compiler and linker to leave the object in the
283// final library/executable instead of stripping it out. In clang/gcc we use
284// __attribute__((used)) to do that.
285# define ARCH_CONSTRUCTOR(_name, _priority) \
286 static void _name(); \
287 namespace { \
288 __declspec(allocate(".pxrctor")) \
289 extern const ARCH_NS::Arch_ConstructorEntry \
290 _ARCH_CAT_NOEXPAND(arch_ctor_, _name) = { \
291 reinterpret_cast<ARCH_NS::Arch_ConstructorEntry::Type>(&_name), \
292 static_cast<unsigned>(ARCH_VERSION), \
293 _priority \
294 }; \
295 } \
296 _ARCH_ENSURE_PER_LIB_INIT(ARCH_NS::Arch_ConstructorInit, _archCtorInit); \
297 static void _name()
298
299 // Emit a Arch_ConstructorEntry in the .pxrdtor section.
300# define ARCH_DESTRUCTOR(_name, _priority) \
301 static void _name(); \
302 namespace { \
303 __declspec(allocate(".pxrdtor")) \
304 extern const ARCH_NS::Arch_ConstructorEntry \
305 _ARCH_CAT_NOEXPAND(arch_dtor_, _name) = { \
306 reinterpret_cast<ARCH_NS::Arch_ConstructorEntry::Type>(&_name), \
307 static_cast<unsigned>(ARCH_VERSION), \
308 _priority \
309 }; \
310 } \
311 _ARCH_ENSURE_PER_LIB_INIT(ARCH_NS::Arch_ConstructorInit, _archCtorInit); \
312 static void _name()
313
314#else
315
316// Leave macros undefined so we'll fail to build on a new system/compiler
317// rather than fail mysteriously at runtime.
318
319#endif
320
321ARCH_NAMESPACE_CLOSE_SCOPE
322
323#endif // PXR_ARCH_ATTRIBUTES_H
Defines symbol visibility macros.
#define ARCH_HIDDEN
Definition export.h:166
StaticInit Arch_PerLibInit< StaticInit >::init
Definition attributes.h:202
Arch_PerLibInit()
Definition attributes.h:196