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