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
19#include <memory>
20
21PXR_NAMESPACE_OPEN_SCOPE
22
23#if defined(doxygen)
24
36# define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
37
50# define ARCH_SCANF_FUNCTION(_fmt, _firstArg)
51
60# define ARCH_NOINLINE
61
74# define ARCH_UNUSED_ARG
75
89# define ARCH_UNUSED_FUNCTION
90
109# define ARCH_USED_FUNCTION
110
124# define ARCH_CONSTRUCTOR(_name, _priority)
125
139# define ARCH_DESTRUCTOR(_name, _priority)
140
147# define ARCH_EMPTY_BASES
148
170# define ARCH_NO_SANITIZE_ADDRESS_FUNCTION
171
172#elif defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG)
173
174# define ARCH_PRINTF_FUNCTION(_fmt, _firstArg) \
175 __attribute__((format(printf, _fmt, _firstArg)))
176# define ARCH_SCANF_FUNCTION(_fmt, _firstArg) \
177 __attribute__((format(scanf, _fmt, _firstArg)))
178# define ARCH_NOINLINE __attribute__((noinline))
179# define ARCH_ALWAYS_INLINE __attribute__((always_inline))
180# define ARCH_UNUSED_ARG __attribute__ ((unused))
181# define ARCH_UNUSED_FUNCTION __attribute__((unused))
182# define ARCH_USED_FUNCTION __attribute__((used))
183# define ARCH_EMPTY_BASES
184
185#if defined(ARCH_SANITIZE_ADDRESS)
186# define ARCH_NO_SANITIZE_ADDRESS_FUNCTION \
187 __attribute__((no_sanitize_address))
188#else
189# define ARCH_NO_SANITIZE_ADDRESS_FUNCTION
190#endif
191
192// Function attributes for other sanitizers (thread, undefined behavior, etc.)
193// intentionally omitted until support is added
194
195#elif defined(ARCH_COMPILER_MSVC)
196
197# define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
198# define ARCH_SCANF_FUNCTION(_fmt, _firstArg)
199# define ARCH_NOINLINE // __declspec(noinline)
200# define ARCH_ALWAYS_INLINE
201# define ARCH_UNUSED_ARG
202# define ARCH_UNUSED_FUNCTION
203# define ARCH_USED_FUNCTION
204# define ARCH_EMPTY_BASES __declspec(empty_bases)
205
206#if defined(ARCH_SANITIZE_ADDRESS)
207# define ARCH_NO_SANITIZE_ADDRESS_FUNCTION \
208 __declspec(no_sanitize_address)
209#else
210# define ARCH_NO_SANITIZE_ADDRESS_FUNCTION
211#endif
212
213// Function attributes for other sanitizers (thread, undefined behavior, etc.)
214// intentionally omitted until support is added
215
216#else
217
218// Leave macros undefined so we'll fail to build on a new system/compiler
219// rather than fail mysteriously at runtime.
220
221#endif
222
223// Helper to do on-demand static initialization. We need to insert per-library
224// static initializers if the ARCH_CONSTRUCTOR macros are used, etc, but we
225// don't want that to happen otherwise. This mechanism makes that possible. It
226// works by creating a class template (Arch_PerLibInit) that has hidden
227// visibility and a static member of its template parameter (StaticInit). In
228// its constructor, it "uses" its static member 'init', in order to ensure it
229// gets instantiated. Since it's a static member, it gets initialized only if
230// it's instantiated. This lets us have macros like ARCH_CONSTRUCTOR() that
231// require a static initializer, but to only emit that static initializer in
232// translation units that actually invoke the macro. Clients typically do this
233// by way of the _ARCH_ENSURE_PER_LIB_INIT macro. This is tested on all current
234// supported compilers (clang, gcc, msvc). The hidden visibility is required to
235// ensure that each library gets its own initialization. Without it, on Linux,
236// there would be exactly *one* initialization no matter how many libraries are
237// loaded.
238template <class StaticInit>
239struct ARCH_HIDDEN Arch_PerLibInit {
240 Arch_PerLibInit() { /* "use" of init here forces instantiation */
241 (void)init; }
242private:
243 static StaticInit init;
244};
245template <class StaticInit>
246StaticInit Arch_PerLibInit<StaticInit>::init;
247
248#define _ARCH_CAT_NOEXPAND(a, b) a ## b
249#define _ARCH_CAT(a, b) _ARCH_CAT_NOEXPAND(a, b)
250#define _ARCH_ENSURE_PER_LIB_INIT(T, prefix) \
251 static Arch_PerLibInit<T> _ARCH_CAT(prefix, __COUNTER__)
252
253#if defined(doxygen)
254
255// The macros are already defined above in doxygen.
256
257#elif defined(ARCH_OS_DARWIN)
258
259// Entry for a constructor/destructor in the custom section.
260struct Arch_ConstructorEntry {
261 typedef void (*Type)(void);
262 Type function;
263 unsigned int version:24; // USD version
264 unsigned int priority:8; // Priority of function
265};
266
267// Emit a Arch_ConstructorEntry in the __Data,pxrctor section.
268# define ARCH_CONSTRUCTOR(_name, _priority) \
269 static void _name(); \
270 static const Arch_ConstructorEntry _ARCH_CAT_NOEXPAND(arch_ctor_, _name) \
271 __attribute__((used, section("__DATA,pxrctor"))) = { \
272 reinterpret_cast<Arch_ConstructorEntry::Type>(&_name), \
273 static_cast<unsigned>(PXR_VERSION), \
274 _priority \
275 }; \
276 static void _name()
277
278// Emit a Arch_ConstructorEntry in the __Data,pxrdtor section.
279# define ARCH_DESTRUCTOR(_name, _priority) \
280 static void _name(); \
281 static const Arch_ConstructorEntry _ARCH_CAT_NOEXPAND(arch_dtor_, _name) \
282 __attribute__((used, section("__DATA,pxrdtor"))) = { \
283 reinterpret_cast<Arch_ConstructorEntry::Type>(&_name), \
284 static_cast<unsigned>(PXR_VERSION), \
285 _priority \
286 }; \
287 static void _name()
288
289#elif defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG)
290
291// The used attribute is required to prevent these apparently unused functions
292// from being removed by the linker.
293# define ARCH_CONSTRUCTOR(_name, _priority) \
294 __attribute__((used, section(".pxrctor"), constructor((_priority) + 100))) \
295 static void _name()
296# define ARCH_DESTRUCTOR(_name, _priority) \
297 __attribute__((used, section(".pxrdtor"), destructor((_priority) + 100))) \
298 static void _name()
299
300#elif defined(ARCH_OS_WINDOWS)
301
302# include "pxr/base/arch/api.h"
303
304// Entry for a constructor/destructor in the custom section.
305 __declspec(align(16))
306 struct Arch_ConstructorEntry {
307 typedef void (__cdecl *Type)(void);
308 Type function;
309 unsigned int version:24; // USD version
310 unsigned int priority:8; // Priority of function
311 };
312
313// Declare the special sections.
314# pragma section(".pxrctor", read)
315# pragma section(".pxrdtor", read)
316
317// Objects of this type run the ARCH_CONSTRUCTOR and ARCH_DESTRUCTOR functions
318// for the library containing the object in the c'tor and d'tor, respectively.
319// Each HMODULE is handled at most once.
320struct Arch_ConstructorInit {
321 ARCH_API Arch_ConstructorInit();
322 ARCH_API ~Arch_ConstructorInit();
323};
324
325// Emit an Arch_ConstructorEntry in the .pxrctor section. The
326// arch_{c,d}tor_unused assignment is a workaround to ensure arch_{c,d}tor
327// isn't removed when /Zc:inline is enabled. In clang/gcc we use
328// __attribute__((used)) to do that.
329# define ARCH_CONSTRUCTOR(_name, _priority) \
330 static void _name(); \
331 namespace { \
332 __declspec(allocate(".pxrctor")) \
333 static const Arch_ConstructorEntry \
334 _ARCH_CAT_NOEXPAND(arch_ctor_, _name) = { \
335 reinterpret_cast<Arch_ConstructorEntry::Type>(&_name), \
336 static_cast<unsigned>(PXR_VERSION), \
337 _priority \
338 }; \
339 void _ARCH_CAT_NOEXPAND(arch_ctor_unused, _name)() { \
340 static const auto unused = \
341 std::addressof(_ARCH_CAT_NOEXPAND(arch_ctor_, _name)); \
342 } \
343 } \
344 _ARCH_ENSURE_PER_LIB_INIT(Arch_ConstructorInit, _archCtorInit); \
345 static void _name()
346
347 // Emit a Arch_ConstructorEntry in the .pxrdtor section.
348# define ARCH_DESTRUCTOR(_name, _priority) \
349 static void _name(); \
350 namespace { \
351 __declspec(allocate(".pxrdtor")) \
352 static const Arch_ConstructorEntry \
353 _ARCH_CAT_NOEXPAND(arch_dtor_, _name) = { \
354 reinterpret_cast<Arch_ConstructorEntry::Type>(&_name), \
355 static_cast<unsigned>(PXR_VERSION), \
356 _priority \
357 }; \
358 void _ARCH_CAT_NOEXPAND(arch_dtor_unused, _name)() { \
359 static const auto unused = \
360 std::addressof(_ARCH_CAT_NOEXPAND(arch_dtor_, _name)); \
361 } \
362 } \
363 _ARCH_ENSURE_PER_LIB_INIT(Arch_ConstructorInit, _archCtorInit); \
364 static void _name()
365
366#else
367
368// Leave macros undefined so we'll fail to build on a new system/compiler
369// rather than fail mysteriously at runtime.
370
371#endif
372
373PXR_NAMESPACE_CLOSE_SCOPE
374
375#endif // PXR_BASE_ARCH_ATTRIBUTES_H
Defines symbol visibility macros.