Skip to content

Commit 6fb5a57

Browse files
acoates-mshtpivdannyvv
authored andcommitted
Fix ARM64 layout issues (microsoft#10071)
* [0.64] Fix ARM64 layout issues in Office (microsoft#8689) * Change the definition of YGUndefined from NAN (contra the comment in YGValue, MSVC does define NAN) to __builtin_nanf("0"), which generates a quiet NaN. The problem with NAN is that corecrt_math.h defines it as: Which *seems* fine! However, because we are compiling with /fp:precise (see: microsoft#4122 for more details), that multiplication actually happens at runtime. And, unfortunately, we're sometimes seeing MXCSR set to round down (i.e., the_MM_ROUND_DOWN flag is set)), which, combined with th SSE instructions that happen to run here (specifically, cvtpd2ps), cause NAN, and thus YGUndefined, to yield a value of 0! What happens is that cvtpd2ps, when rounding down, converts 1#.INF in double-precision not to 1#.INF in single-precision, but instead to FLT_MAX!!! And, of course, FLT_MAX*0 is 0, not qNaN. Oops. Anyways, using __builting_nanf("0") just loads 0x7FC0000 into xmm0, rather than doing any math, so, even with /fp:precise + bad rounding modes, YGUndefined is, in fact, a quiet NaN. * Revert "Change the definition of YGUndefined from NAN (contra the comment in" This reverts commit 3fb68a2. Rather than trying to fork YGValue.h, we'll address the underlying problem by not using /fp:strict for yoga.cpp * Compiling yoga.cpp with /fp:strict causes microsoft#8675. We use this flag to address microsoft#4122, but in my manual testing, as well by inspecting the disassembly that seemed to be responsible for issue 4122, this workaround is no longer necessary. * Patch yoga to use better definition for YGUndefined * Change files Co-authored-by: dannyvv <[email protected]> Co-authored-by: Andrew Coates <[email protected]> * Fix change file * react-native-platform-override upgrade Co-authored-by: Harold Pratt <[email protected]> Co-authored-by: dannyvv <[email protected]>
1 parent 4239e74 commit 6fb5a57

File tree

3 files changed

+108
-1
lines changed

3 files changed

+108
-1
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "Change the definition of YGUndefined from NAN to __builtin_nanf(\"0\")",
4+
"packageName": "react-native-windows",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <math.h>
11+
#include "YGEnums.h"
12+
#include "YGMacros.h"
13+
14+
#if defined(_MSC_VER) && defined(__clang__)
15+
#define COMPILING_WITH_CLANG_ON_WINDOWS
16+
#endif
17+
#if defined(COMPILING_WITH_CLANG_ON_WINDOWS)
18+
#include <limits>
19+
constexpr float YGUndefined = std::numeric_limits<float>::quiet_NaN();
20+
#else
21+
YG_EXTERN_C_BEGIN
22+
23+
#if defined(_MSC_VER)
24+
#define YGUndefined __builtin_nanf("0")
25+
#else
26+
#define YGUndefined NAN
27+
#endif
28+
29+
#endif
30+
31+
typedef struct YGValue {
32+
float value;
33+
YGUnit unit;
34+
} YGValue;
35+
36+
YOGA_EXPORT extern const YGValue YGValueAuto;
37+
YOGA_EXPORT extern const YGValue YGValueUndefined;
38+
YOGA_EXPORT extern const YGValue YGValueZero;
39+
40+
#if !defined(COMPILING_WITH_CLANG_ON_WINDOWS)
41+
YG_EXTERN_C_END
42+
#endif
43+
#undef COMPILING_WITH_CLANG_ON_WINDOWS
44+
45+
#ifdef __cplusplus
46+
47+
inline bool operator==(const YGValue& lhs, const YGValue& rhs) {
48+
if (lhs.unit != rhs.unit) {
49+
return false;
50+
}
51+
52+
switch (lhs.unit) {
53+
case YGUnitUndefined:
54+
case YGUnitAuto:
55+
return true;
56+
case YGUnitPoint:
57+
case YGUnitPercent:
58+
return lhs.value == rhs.value;
59+
}
60+
61+
return false;
62+
}
63+
64+
inline bool operator!=(const YGValue& lhs, const YGValue& rhs) {
65+
return !(lhs == rhs);
66+
}
67+
68+
inline YGValue operator-(const YGValue& value) {
69+
return {-value.value, value.unit};
70+
}
71+
72+
namespace facebook {
73+
namespace yoga {
74+
namespace literals {
75+
76+
inline YGValue operator"" _pt(long double value) {
77+
return YGValue{static_cast<float>(value), YGUnitPoint};
78+
}
79+
inline YGValue operator"" _pt(unsigned long long value) {
80+
return operator"" _pt(static_cast<long double>(value));
81+
}
82+
83+
inline YGValue operator"" _percent(long double value) {
84+
return YGValue{static_cast<float>(value), YGUnitPercent};
85+
}
86+
inline YGValue operator"" _percent(unsigned long long value) {
87+
return operator"" _percent(static_cast<long double>(value));
88+
}
89+
90+
} // namespace literals
91+
} // namespace yoga
92+
} // namespace facebook
93+
94+
#endif

vnext/overrides.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@
7474
"baseHash": "95a6fd14e80719f9796942ffe59dd850a56d544c",
7575
"issue": 9791
7676
},
77+
{
78+
"type": "patch",
79+
"file": "ReactCommon/TEMP_UntilReactCommonUpdate/yoga/yoga/YGValue.h",
80+
"baseFile": "ReactCommon/yoga/yoga/YGValue.h",
81+
"baseHash": "0b6b49a41787b7f5caee1792af488c66d33db3d8"
82+
},
7783
{
7884
"type": "patch",
7985
"file": "ReactCommon/Yoga.cpp",
@@ -514,4 +520,4 @@
514520
"file": "src/typings-index.ts"
515521
}
516522
]
517-
}
523+
}

0 commit comments

Comments
 (0)