1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_PLATFORM_GLOBALS_H_
6#define RUNTIME_PLATFORM_GLOBALS_H_
7
8#if __cplusplus >= 201703L // C++17
9#define FALL_THROUGH [[fallthrough]] // NOLINT
10#elif defined(__GNUC__) && __GNUC__ >= 7
11#define FALL_THROUGH __attribute__((fallthrough));
12#elif defined(__clang__)
13#define FALL_THROUGH [[clang::fallthrough]] // NOLINT
14#else
15#define FALL_THROUGH ((void)0)
16#endif
17
18#if defined(GOOGLE3)
19// google3 builds use NDEBUG to indicate non-debug builds which is different
20// from the way the Dart project expects it: DEBUG indicating a debug build.
21#if !defined(NDEBUG) && !defined(DEBUG)
22#define DEBUG
23#endif // !NDEBUG && !DEBUG
24#endif // GOOGLE3
25
26// __STDC_FORMAT_MACROS has to be defined before including <inttypes.h> to
27// enable platform independent printf format specifiers.
28#ifndef __STDC_FORMAT_MACROS
29#define __STDC_FORMAT_MACROS
30#endif
31
32#if defined(_WIN32)
33// Cut down on the amount of stuff that gets included via windows.h.
34#if !defined(WIN32_LEAN_AND_MEAN)
35#define WIN32_LEAN_AND_MEAN
36#endif
37
38#if !defined(NOMINMAX)
39#define NOMINMAX
40#endif
41
42#if !defined(NOKERNEL)
43#define NOKERNEL
44#endif
45
46#if !defined(NOSERVICE)
47#define NOSERVICE
48#endif
49
50#if !defined(NOSOUND)
51#define NOSOUND
52#endif
53
54#if !defined(NOMCX)
55#define NOMCX
56#endif
57
58#if !defined(UNICODE)
59#define _UNICODE
60#define UNICODE
61#endif
62
63#include <Rpc.h>
64#include <VersionHelpers.h>
65#include <intrin.h>
66#include <shellapi.h>
67#include <windows.h>
68#include <winsock2.h>
69#endif // defined(_WIN32)
70
71#if !defined(_WIN32)
72#include <arpa/inet.h>
73#include <unistd.h>
74#endif // !defined(_WIN32)
75
76#include <float.h>
77#include <inttypes.h>
78#include <limits.h>
79#include <math.h>
80#include <stdarg.h>
81#include <stddef.h>
82#include <stdint.h>
83#include <stdio.h>
84#include <stdlib.h>
85#include <string.h>
86#include <sys/types.h>
87
88#if defined(_WIN32)
89#include "platform/floating_point_win.h"
90#endif // defined(_WIN32)
91
92#if !defined(_WIN32)
93#include "platform/floating_point.h"
94#endif // !defined(_WIN32)
95
96// Target OS detection.
97// for more information on predefined macros:
98// - http://msdn.microsoft.com/en-us/library/b0084kay.aspx
99// - with gcc, run: "echo | gcc -E -dM -"
100#if defined(__ANDROID__)
101
102// Check for Android first, to determine its difference from Linux.
103#define HOST_OS_ANDROID 1
104
105#elif defined(__linux__) || defined(__FreeBSD__)
106
107// Generic Linux.
108#define HOST_OS_LINUX 1
109
110#elif defined(__APPLE__)
111
112// Define the flavor of Mac OS we are running on.
113#include <TargetConditionals.h>
114// TODO(iposva): Rename HOST_OS_MACOS to HOST_OS_MAC to inherit
115// the value defined in TargetConditionals.h
116#define HOST_OS_MACOS 1
117#if TARGET_OS_IPHONE
118#define HOST_OS_IOS 1
119#endif
120
121#elif defined(_WIN32)
122
123// Windows, both 32- and 64-bit, regardless of the check for _WIN32.
124#define HOST_OS_WINDOWS 1
125
126#elif defined(__Fuchsia__)
127#define HOST_OS_FUCHSIA
128
129#elif !defined(HOST_OS_FUCHSIA)
130#error Automatic target os detection failed.
131#endif
132
133#if defined(DEBUG)
134#define DEBUG_ONLY(code) code
135#else // defined(DEBUG)
136#define DEBUG_ONLY(code)
137#endif // defined(DEBUG)
138
139#if defined(DEBUG)
140#define UNLESS_DEBUG(code)
141#else // defined(DEBUG)
142#define UNLESS_DEBUG(code) code
143#endif // defined(DEBUG)
144
145namespace dart {
146
147struct simd128_value_t {
148 union {
149 int32_t int_storage[4];
150 float float_storage[4];
151 double double_storage[2];
152 };
153 simd128_value_t& readFrom(const float* v) {
154 float_storage[0] = v[0];
155 float_storage[1] = v[1];
156 float_storage[2] = v[2];
157 float_storage[3] = v[3];
158 return *this;
159 }
160 simd128_value_t& readFrom(const int32_t* v) {
161 int_storage[0] = v[0];
162 int_storage[1] = v[1];
163 int_storage[2] = v[2];
164 int_storage[3] = v[3];
165 return *this;
166 }
167 simd128_value_t& readFrom(const double* v) {
168 double_storage[0] = v[0];
169 double_storage[1] = v[1];
170 return *this;
171 }
172 simd128_value_t& readFrom(const simd128_value_t* v) {
173 *this = *v;
174 return *this;
175 }
176 void writeTo(float* v) {
177 v[0] = float_storage[0];
178 v[1] = float_storage[1];
179 v[2] = float_storage[2];
180 v[3] = float_storage[3];
181 }
182 void writeTo(int32_t* v) {
183 v[0] = int_storage[0];
184 v[1] = int_storage[1];
185 v[2] = int_storage[2];
186 v[3] = int_storage[3];
187 }
188 void writeTo(double* v) {
189 v[0] = double_storage[0];
190 v[1] = double_storage[1];
191 }
192 void writeTo(simd128_value_t* v) { *v = *this; }
193};
194
195// Processor architecture detection. For more info on what's defined, see:
196// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
197// http://www.agner.org/optimize/calling_conventions.pdf
198// or with gcc, run: "echo | gcc -E -dM -"
199#if defined(_M_X64) || defined(__x86_64__)
200#define HOST_ARCH_X64 1
201#define ARCH_IS_64_BIT 1
202#define kFpuRegisterSize 16
203typedef simd128_value_t fpu_register_t;
204#elif defined(_M_IX86) || defined(__i386__)
205#define HOST_ARCH_IA32 1
206#define ARCH_IS_32_BIT 1
207#define kFpuRegisterSize 16
208typedef simd128_value_t fpu_register_t;
209#elif defined(__ARMEL__)
210#define HOST_ARCH_ARM 1
211#define ARCH_IS_32_BIT 1
212#define kFpuRegisterSize 16
213// Mark the fact that we have defined simd_value_t.
214#define SIMD_VALUE_T_
215typedef struct {
216 union {
217 uint32_t u;
218 float f;
219 } data_[4];
220} simd_value_t;
221typedef simd_value_t fpu_register_t;
222#define simd_value_safe_load(addr) (*reinterpret_cast<simd_value_t*>(addr))
223#define simd_value_safe_store(addr, value) \
224 do { \
225 reinterpret_cast<simd_value_t*>(addr)->data_[0] = value.data_[0]; \
226 reinterpret_cast<simd_value_t*>(addr)->data_[1] = value.data_[1]; \
227 reinterpret_cast<simd_value_t*>(addr)->data_[2] = value.data_[2]; \
228 reinterpret_cast<simd_value_t*>(addr)->data_[3] = value.data_[3]; \
229 } while (0)
230
231#elif defined(__aarch64__)
232#define HOST_ARCH_ARM64 1
233#define ARCH_IS_64_BIT 1
234#define kFpuRegisterSize 16
235typedef simd128_value_t fpu_register_t;
236#else
237#error Architecture was not detected as supported by Dart.
238#endif
239
240// DART_FORCE_INLINE strongly hints to the compiler that a function should
241// be inlined. Your function is not guaranteed to be inlined but this is
242// stronger than just using "inline".
243// See: http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx for an
244// explanation of some the cases when a function can never be inlined.
245#ifdef _MSC_VER
246#define DART_FORCE_INLINE __forceinline
247#elif __GNUC__
248#define DART_FORCE_INLINE inline __attribute__((always_inline))
249#else
250#error Automatic compiler detection failed.
251#endif
252
253// DART_NOINLINE tells compiler to never inline a particular function.
254#ifdef _MSC_VER
255#define DART_NOINLINE __declspec(noinline)
256#elif __GNUC__
257#define DART_NOINLINE __attribute__((noinline))
258#else
259#error Automatic compiler detection failed.
260#endif
261
262#ifdef _MSC_VER
263#elif __GNUC__
264#define DART_HAS_COMPUTED_GOTO 1
265#else
266#error Automatic compiler detection failed.
267#endif
268
269// LIKELY/UNLIKELY give the compiler branch preditions that may affect block
270// scheduling.
271#ifdef __GNUC__
272#define LIKELY(cond) __builtin_expect((cond), 1)
273#define UNLIKELY(cond) __builtin_expect((cond), 0)
274#else
275#define LIKELY(cond) cond
276#define UNLIKELY(cond) cond
277#endif
278
279// DART_UNUSED indicates to the compiler that a variable or typedef is expected
280// to be unused and disables the related warning.
281#ifdef __GNUC__
282#define DART_UNUSED __attribute__((unused))
283#else
284#define DART_UNUSED
285#endif
286
287// DART_USED indicates to the compiler that a global variable or typedef is used
288// disables e.g. the gcc warning "unused-variable"
289#ifdef __GNUC__
290#define DART_USED __attribute__((used))
291#else
292#define DART_USED
293#endif
294
295// DART_NORETURN indicates to the compiler that a function does not return.
296// It should be used on functions that unconditionally call functions like
297// exit(), which end the program. We use it to avoid compiler warnings in
298// callers of DART_NORETURN functions.
299#ifdef _MSC_VER
300#define DART_NORETURN __declspec(noreturn)
301#elif __GNUC__
302#define DART_NORETURN __attribute__((noreturn))
303#else
304#error Automatic compiler detection failed.
305#endif
306
307#ifdef _MSC_VER
308#define DART_PRETTY_FUNCTION __FUNCSIG__
309#elif __GNUC__
310#define DART_PRETTY_FUNCTION __PRETTY_FUNCTION__
311#else
312#error Automatic compiler detection failed.
313#endif
314
315#if !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_X64) && \
316 !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_ARM64)
317// No target architecture specified pick the one matching the host architecture.
318#if defined(HOST_ARCH_ARM)
319#define TARGET_ARCH_ARM 1
320#elif defined(HOST_ARCH_X64)
321#define TARGET_ARCH_X64 1
322#elif defined(HOST_ARCH_IA32)
323#define TARGET_ARCH_IA32 1
324#elif defined(HOST_ARCH_ARM64)
325#define TARGET_ARCH_ARM64 1
326#else
327#error Automatic target architecture detection failed.
328#endif
329#endif
330
331#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
332#define TARGET_ARCH_IS_32_BIT 1
333#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
334#define TARGET_ARCH_IS_64_BIT 1
335#else
336#error Automatic target architecture detection failed.
337#endif
338
339// Verify that host and target architectures match, we cannot
340// have a 64 bit Dart VM generating 32 bit code or vice-versa.
341#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
342#if !defined(ARCH_IS_64_BIT)
343#error Mismatched Host/Target architectures.
344#endif // !defined(ARCH_IS_64_BIT)
345#elif defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
346#if defined(HOST_ARCH_X64) && defined(TARGET_ARCH_ARM)
347// This is simarm_x64, which is the only case where host/target architecture
348// mismatch is allowed.
349#define IS_SIMARM_X64 1
350#elif !defined(ARCH_IS_32_BIT)
351#error Mismatched Host/Target architectures.
352#endif // !defined(ARCH_IS_32_BIT)
353#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
354
355// Determine whether we will be using the simulator.
356#if defined(TARGET_ARCH_IA32)
357// No simulator used.
358#elif defined(TARGET_ARCH_X64)
359// No simulator used.
360#elif defined(TARGET_ARCH_ARM)
361#if !defined(HOST_ARCH_ARM)
362#define TARGET_HOST_MISMATCH 1
363#if !defined(IS_SIMARM_X64)
364#define USING_SIMULATOR 1
365#endif
366#endif
367
368#elif defined(TARGET_ARCH_ARM64)
369#if !defined(HOST_ARCH_ARM64)
370#define USING_SIMULATOR 1
371#endif
372
373#else
374#error Unknown architecture.
375#endif
376
377#if defined(ARCH_IS_32_BIT) || defined(IS_SIMARM_X64)
378#define TARGET_ARCH_IS_32_BIT 1
379#elif defined(ARCH_IS_64_BIT)
380#define TARGET_ARCH_IS_64_BIT 1
381#endif
382
383#if !defined(TARGET_OS_ANDROID) && !defined(TARGET_OS_FUCHSIA) && \
384 !defined(TARGET_OS_MACOS_IOS) && !defined(TARGET_OS_LINUX) && \
385 !defined(TARGET_OS_MACOS) && !defined(TARGET_OS_WINDOWS)
386// No target OS specified; pick the one matching the host OS.
387#if defined(HOST_OS_ANDROID)
388#define TARGET_OS_ANDROID 1
389#elif defined(HOST_OS_FUCHSIA)
390#define TARGET_OS_FUCHSIA 1
391#elif defined(HOST_OS_IOS)
392#define TARGET_OS_MACOS 1
393#define TARGET_OS_MACOS_IOS 1
394#elif defined(HOST_OS_LINUX)
395#define TARGET_OS_LINUX 1
396#elif defined(HOST_OS_MACOS)
397#define TARGET_OS_MACOS 1
398#elif defined(HOST_OS_WINDOWS)
399#define TARGET_OS_WINDOWS 1
400#else
401#error Automatic target OS detection failed.
402#endif
403#endif
404
405// Determine whether dual mapping of code pages is supported.
406// We test dual mapping on linux x64 and deploy it on fuchsia.
407#if !defined(DART_PRECOMPILED_RUNTIME) && \
408 (defined(TARGET_OS_LINUX) && defined(TARGET_ARCH_X64) || \
409 defined(TARGET_OS_FUCHSIA))
410#define DUAL_MAPPING_SUPPORTED 1
411#endif
412
413#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
414#define SUPPORT_UNBOXED_INSTANCE_FIELDS
415#endif
416
417// Short form printf format specifiers
418#define Pd PRIdPTR
419#define Pu PRIuPTR
420#define Px PRIxPTR
421#define PX PRIXPTR
422#define Pd32 PRId32
423#define Pu32 PRIu32
424#define Px32 PRIx32
425#define PX32 PRIX32
426#define Pd64 PRId64
427#define Pu64 PRIu64
428#define Px64 PRIx64
429#define PX64 PRIX64
430
431// Zero-padded pointer
432#if defined(ARCH_IS_32_BIT)
433#define Pp "08" PRIxPTR
434#else
435#define Pp "016" PRIxPTR
436#endif
437
438// Suffixes for 64-bit integer literals.
439#ifdef _MSC_VER
440#define DART_INT64_C(x) x##I64
441#define DART_UINT64_C(x) x##UI64
442#else
443#define DART_INT64_C(x) x##LL
444#define DART_UINT64_C(x) x##ULL
445#endif
446
447// Replace calls to strtoll with _strtoi64 on Windows.
448#ifdef _MSC_VER
449#define strtoll _strtoi64
450#endif
451
452// The following macro works on both 32 and 64-bit platforms.
453// Usage: instead of writing 0x1234567890123456ULL
454// write DART_2PART_UINT64_C(0x12345678,90123456);
455#define DART_2PART_UINT64_C(a, b) \
456 (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
457
458// Integer constants.
459const int8_t kMinInt8 = 0x80;
460const int8_t kMaxInt8 = 0x7F;
461const uint8_t kMaxUint8 = 0xFF;
462const int16_t kMinInt16 = 0x8000;
463const int16_t kMaxInt16 = 0x7FFF;
464const uint16_t kMaxUint16 = 0xFFFF;
465const int32_t kMinInt32 = 0x80000000;
466const int32_t kMaxInt32 = 0x7FFFFFFF;
467const uint32_t kMaxUint32 = 0xFFFFFFFF;
468const int64_t kMinInt64 = DART_INT64_C(0x8000000000000000);
469const int64_t kMaxInt64 = DART_INT64_C(0x7FFFFFFFFFFFFFFF);
470const int kMinInt = INT_MIN;
471const int kMaxInt = INT_MAX;
472const int64_t kMinInt64RepresentableAsDouble = kMinInt64;
473const int64_t kMaxInt64RepresentableAsDouble = DART_INT64_C(0x7FFFFFFFFFFFFC00);
474const uint64_t kMaxUint64 = DART_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF);
475const int64_t kSignBitDouble = DART_INT64_C(0x8000000000000000);
476
477// Types for native machine words. Guaranteed to be able to hold pointers and
478// integers.
479typedef intptr_t word;
480typedef uintptr_t uword;
481
482// Size of a class id assigned to concrete, abstract and top-level classes.
483//
484// We use a signed integer type here to make it comparable with intptr_t.
485typedef int32_t classid_t;
486
487// Byte sizes.
488const int kWordSize = sizeof(word);
489const int kDoubleSize = sizeof(double); // NOLINT
490const int kFloatSize = sizeof(float); // NOLINT
491const int kQuadSize = 4 * kFloatSize;
492const int kSimd128Size = sizeof(simd128_value_t); // NOLINT
493const int kInt64Size = sizeof(int64_t); // NOLINT
494const int kInt32Size = sizeof(int32_t); // NOLINT
495const int kInt16Size = sizeof(int16_t); // NOLINT
496#ifdef ARCH_IS_32_BIT
497const int kWordSizeLog2 = 2;
498const uword kUwordMax = kMaxUint32;
499#else
500const int kWordSizeLog2 = 3;
501const uword kUwordMax = kMaxUint64;
502#endif
503
504// Bit sizes.
505const int kBitsPerByte = 8;
506const int kBitsPerByteLog2 = 3;
507const int kBitsPerInt32 = kInt32Size * kBitsPerByte;
508const int kBitsPerInt64 = kInt64Size * kBitsPerByte;
509const int kBitsPerWord = kWordSize * kBitsPerByte;
510const int kBitsPerWordLog2 = kWordSizeLog2 + kBitsPerByteLog2;
511
512// System-wide named constants.
513const intptr_t KB = 1024;
514const intptr_t KBLog2 = 10;
515const intptr_t MB = KB * KB;
516const intptr_t MBLog2 = KBLog2 + KBLog2;
517const intptr_t GB = MB * KB;
518const intptr_t GBLog2 = MBLog2 + KBLog2;
519
520const intptr_t KBInWords = KB >> kWordSizeLog2;
521const intptr_t KBInWordsLog2 = KBLog2 - kWordSizeLog2;
522const intptr_t MBInWords = KB * KBInWords;
523const intptr_t MBInWordsLog2 = KBLog2 + KBInWordsLog2;
524const intptr_t GBInWords = MB * KBInWords;
525const intptr_t GBInWordsLog2 = MBLog2 + KBInWordsLog2;
526
527// Helpers to round memory sizes to human readable values.
528inline intptr_t RoundWordsToKB(intptr_t size_in_words) {
529 return (size_in_words + (KBInWords >> 1)) >> KBInWordsLog2;
530}
531inline intptr_t RoundWordsToMB(intptr_t size_in_words) {
532 return (size_in_words + (MBInWords >> 1)) >> MBInWordsLog2;
533}
534inline intptr_t RoundWordsToGB(intptr_t size_in_words) {
535 return (size_in_words + (GBInWords >> 1)) >> GBInWordsLog2;
536}
537
538const intptr_t kIntptrOne = 1;
539const intptr_t kIntptrMin = (kIntptrOne << (kBitsPerWord - 1));
540const intptr_t kIntptrMax = ~kIntptrMin;
541
542// Time constants.
543const int kMillisecondsPerSecond = 1000;
544const int kMicrosecondsPerMillisecond = 1000;
545const int kMicrosecondsPerSecond =
546 (kMicrosecondsPerMillisecond * kMillisecondsPerSecond);
547const int kNanosecondsPerMicrosecond = 1000;
548const int kNanosecondsPerMillisecond =
549 (kNanosecondsPerMicrosecond * kMicrosecondsPerMillisecond);
550const int kNanosecondsPerSecond =
551 (kNanosecondsPerMicrosecond * kMicrosecondsPerSecond);
552
553// Helpers to scale micro second times to human understandable values.
554inline double MicrosecondsToSeconds(int64_t micros) {
555 return static_cast<double>(micros) / kMicrosecondsPerSecond;
556}
557inline double MicrosecondsToMilliseconds(int64_t micros) {
558 return static_cast<double>(micros) / kMicrosecondsPerMillisecond;
559}
560
561// A macro to disallow the copy constructor and operator= functions.
562// This should be used in the private: declarations for a class.
563#if !defined(DISALLOW_COPY_AND_ASSIGN)
564#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
565 private: \
566 TypeName(const TypeName&) = delete; \
567 void operator=(const TypeName&) = delete
568#endif // !defined(DISALLOW_COPY_AND_ASSIGN)
569
570// A macro to disallow all the implicit constructors, namely the default
571// constructor, copy constructor and operator= functions. This should be
572// used in the private: declarations for a class that wants to prevent
573// anyone from instantiating it. This is especially useful for classes
574// containing only static methods.
575#if !defined(DISALLOW_IMPLICIT_CONSTRUCTORS)
576#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
577 private: \
578 TypeName() = delete; \
579 DISALLOW_COPY_AND_ASSIGN(TypeName)
580#endif // !defined(DISALLOW_IMPLICIT_CONSTRUCTORS)
581
582// Macro to disallow allocation in the C++ heap. This should be used
583// in the private section for a class. Don't use UNREACHABLE here to
584// avoid circular dependencies between platform/globals.h and
585// platform/assert.h.
586#if !defined(DISALLOW_ALLOCATION)
587#define DISALLOW_ALLOCATION() \
588 public: \
589 void operator delete(void* pointer) { \
590 fprintf(stderr, "unreachable code\n"); \
591 abort(); \
592 } \
593 \
594 private: \
595 void* operator new(size_t size);
596#endif // !defined(DISALLOW_ALLOCATION)
597
598// The USE(x) template is used to silence C++ compiler warnings issued
599// for unused variables.
600template <typename T>
601static inline void USE(T) {}
602
603// The type-based aliasing rule allows the compiler to assume that
604// pointers of different types (for some definition of different)
605// never alias each other. Thus the following code does not work:
606//
607// float f = foo();
608// int fbits = *(int*)(&f);
609//
610// The compiler 'knows' that the int pointer can't refer to f since
611// the types don't match, so the compiler may cache f in a register,
612// leaving random data in fbits. Using C++ style casts makes no
613// difference, however a pointer to char data is assumed to alias any
614// other pointer. This is the 'memcpy exception'.
615//
616// The bit_cast function uses the memcpy exception to move the bits
617// from a variable of one type to a variable of another type. Of
618// course the end result is likely to be implementation dependent.
619// Most compilers (gcc-4.2 and MSVC 2005) will completely optimize
620// bit_cast away.
621//
622// There is an additional use for bit_cast. Recent gccs will warn when
623// they see casts that may result in breakage due to the type-based
624// aliasing rule. If you have checked that there is no breakage you
625// can use bit_cast to cast one pointer type to another. This confuses
626// gcc enough that it can no longer see that you have cast one pointer
627// type to another thus avoiding the warning.
628template <class D, class S>
629inline D bit_cast(const S& source) {
630 static_assert(sizeof(D) == sizeof(S),
631 "Source and destination must have the same size");
632
633 D destination;
634 // This use of memcpy is safe: source and destination cannot overlap.
635 memcpy(&destination, &source, sizeof(destination));
636 return destination;
637}
638
639// Similar to bit_cast, but allows copying from types of unrelated
640// sizes. This method was introduced to enable the strict aliasing
641// optimizations of GCC 4.4. Basically, GCC mindlessly relies on
642// obscure details in the C++ standard that make reinterpret_cast
643// virtually useless.
644template <class D, class S>
645inline D bit_copy(const S& source) {
646 D destination;
647 // This use of memcpy is safe: source and destination cannot overlap.
648 memcpy(&destination, reinterpret_cast<const void*>(&source),
649 sizeof(destination));
650 return destination;
651}
652
653// On Windows the reentrent version of strtok is called
654// strtok_s. Unify on the posix name strtok_r.
655#if defined(HOST_OS_WINDOWS)
656#define snprintf _sprintf_p
657#define strtok_r strtok_s
658#endif
659
660#if !defined(HOST_OS_WINDOWS)
661#if defined(TEMP_FAILURE_RETRY)
662// TEMP_FAILURE_RETRY is defined in unistd.h on some platforms. We should
663// not use that version, but instead the one in signal_blocker.h, to ensure
664// we disable signal interrupts.
665#undef TEMP_FAILURE_RETRY
666#endif // defined(TEMP_FAILURE_RETRY)
667#endif // !defined(HOST_OS_WINDOWS)
668
669#if __GNUC__
670// Tell the compiler to do printf format string checking if the
671// compiler supports it; see the 'format' attribute in
672// <http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Function-Attributes.html>.
673//
674// N.B.: As the GCC manual states, "[s]ince non-static C++ methods
675// have an implicit 'this' argument, the arguments of such methods
676// should be counted from two, not one."
677#define PRINTF_ATTRIBUTE(string_index, first_to_check) \
678 __attribute__((__format__(__printf__, string_index, first_to_check)))
679#else
680#define PRINTF_ATTRIBUTE(string_index, first_to_check)
681#endif
682
683#if defined(_WIN32)
684#define STDIN_FILENO 0
685#define STDOUT_FILENO 1
686#define STDERR_FILENO 2
687#endif
688
689#ifndef PATH_MAX
690// Most platforms use PATH_MAX, but in Windows it's called MAX_PATH.
691#define PATH_MAX MAX_PATH
692#endif
693
694// Undefine math.h definition which clashes with our condition names.
695#undef OVERFLOW
696
697} // namespace dart
698
699#endif // RUNTIME_PLATFORM_GLOBALS_H_
700