This document is for a version of USD that is under development. See this page for the current release.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
attributes.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_ARCH_ATTRIBUTES_H
8#define PXR_BASE_ARCH_ATTRIBUTES_H
9
15
16#include "pxr/pxr.h"
18
19PXR_NAMESPACE_OPEN_SCOPE
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>
202struct ARCH_HIDDEN Arch_PerLibInit {
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 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 Arch_ConstructorEntry _ARCH_CAT_NOEXPAND(arch_ctor_, _name) \
234 __attribute__((used, section("__DATA,pxrctor"))) = { \
235 reinterpret_cast<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 Arch_ConstructorEntry _ARCH_CAT_NOEXPAND(arch_dtor_, _name) \
245 __attribute__((used, section("__DATA,pxrdtor"))) = { \
246 reinterpret_cast<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 "pxr/base/arch/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 Arch_ConstructorEntry \
297 _ARCH_CAT_NOEXPAND(arch_ctor_, _name) = { \
298 reinterpret_cast<Arch_ConstructorEntry::Type>(&_name), \
299 static_cast<unsigned>(PXR_VERSION), \
300 _priority \
301 }; \
302 } \
303 _ARCH_ENSURE_PER_LIB_INIT(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 Arch_ConstructorEntry \
312 _ARCH_CAT_NOEXPAND(arch_dtor_, _name) = { \
313 reinterpret_cast<Arch_ConstructorEntry::Type>(&_name), \
314 static_cast<unsigned>(PXR_VERSION), \
315 _priority \
316 }; \
317 } \
318 _ARCH_ENSURE_PER_LIB_INIT(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
328PXR_NAMESPACE_CLOSE_SCOPE
329
330#endif // PXR_BASE_ARCH_ATTRIBUTES_H
Defines symbol visibility macros.