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