Skip to content

Commit cb3bf75

Browse files
committed
[llvm][clang] duplicate long double layout logic from clang to LLVM
Information about the size and alignment of `long double` is currently part of clang. Copy this logic to LLVM so it can be used to control lowering of intrinsics. Additionally, add an assertion to make sure Clang and LLVM agree.
1 parent e869ad1 commit cb3bf75

File tree

5 files changed

+252
-2
lines changed

5 files changed

+252
-2
lines changed

clang/include/clang/Basic/TargetInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,10 @@ class TargetInfo : public TransferrableTargetInfo,
12181218
return Triple;
12191219
}
12201220

1221+
/// Assert that layouts for C types computed by Clang are the same as layouts
1222+
/// stored in the LLVM target.
1223+
void validateCLayouts() const;
1224+
12211225
/// Returns the target ID if supported.
12221226
virtual std::optional<std::string> getTargetID() const {
12231227
return std::nullopt;

clang/lib/Basic/TargetInfo.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,24 @@ bool TargetInfo::validateInputConstraint(
925925
return true;
926926
}
927927

928+
void TargetInfo::validateCLayouts() const {
929+
llvm::Triple::CLayouts TripleLayouts = Triple.getCLayouts();
930+
if (__builtin_expect(LongDoubleWidth != TripleLayouts.LongDoubleWidth ||
931+
LongDoubleAlign != TripleLayouts.LongDoubleAlign ||
932+
LongDoubleFormat != TripleLayouts.LongDoubleFormat,
933+
0)) {
934+
fprintf(stderr, "'long double' width got %d, expected %d\n",
935+
LongDoubleWidth, TripleLayouts.LongDoubleWidth);
936+
fprintf(stderr, "'long double' align got %d, expected %d\n",
937+
LongDoubleAlign, TripleLayouts.LongDoubleAlign);
938+
fprintf(
939+
stderr, "'long double' format got %d, expected %d\n",
940+
llvm::APFloatBase::SemanticsToEnum(*LongDoubleFormat),
941+
llvm::APFloatBase::SemanticsToEnum(*TripleLayouts.LongDoubleFormat));
942+
llvm_unreachable("Clang & LLVM layout mismatch");
943+
}
944+
}
945+
928946
void TargetInfo::CheckFixedPointBits() const {
929947
// Check that the number of fractional and integral bits (and maybe sign) can
930948
// fit into the bits given for a fixed point type.

clang/lib/Basic/Targets.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,15 @@ void addCygMingDefines(const LangOptions &Opts, MacroBuilder &Builder) {
109109
// Driver code
110110
//===----------------------------------------------------------------------===//
111111

112-
std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
113-
const TargetOptions &Opts) {
112+
std::unique_ptr<TargetInfo> AllocateTargetImpl(const llvm::Triple &Triple,
113+
const TargetOptions &Opts) {
114114
llvm::Triple::OSType os = Triple.getOS();
115115

116116
switch (Triple.getArch()) {
117117
default:
118118
return nullptr;
119119

120+
// Keep this in sync with llvm Triple.cpp getCLayouts
120121
case llvm::Triple::arc:
121122
return std::make_unique<ARCTargetInfo>(Triple, Opts);
122123

@@ -751,6 +752,15 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
751752
}
752753
}
753754
}
755+
std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
756+
const TargetOptions &Opts) {
757+
758+
std::unique_ptr<TargetInfo> target = AllocateTargetImpl(Triple, Opts);
759+
if (target != nullptr) {
760+
target->validateCLayouts();
761+
}
762+
return target;
763+
}
754764
} // namespace targets
755765
} // namespace clang
756766

llvm/include/llvm/TargetParser/Triple.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_TARGETPARSER_TRIPLE_H
1010
#define LLVM_TARGETPARSER_TRIPLE_H
1111

12+
#include "llvm/ADT/APFloat.h"
1213
#include "llvm/ADT/Twine.h"
1314
#include "llvm/Support/VersionTuple.h"
1415

@@ -1173,6 +1174,23 @@ class Triple {
11731174
/// Returns a canonicalized OS version number for the specified OS.
11741175
static VersionTuple getCanonicalVersionForOS(OSType OSKind,
11751176
const VersionTuple &Version);
1177+
1178+
/// Layouts for C types that are relevant to libc calls generated by LLVM
1179+
struct CLayouts {
1180+
unsigned char LongDoubleWidth;
1181+
unsigned char LongDoubleAlign;
1182+
const fltSemantics *LongDoubleFormat;
1183+
};
1184+
1185+
/// Provide default layouts relevant to C. Frontends may override these
1186+
/// values.
1187+
CLayouts getCLayouts() const;
1188+
1189+
/// Return true if `long double` and `__float128` have the same layout.
1190+
bool isLongDoubleF128() const {
1191+
// TODO: do we also need to check alignment?
1192+
return getCLayouts().LongDoubleWidth == 128;
1193+
}
11761194
};
11771195

11781196
} // End llvm namespace

llvm/lib/TargetParser/Triple.cpp

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,206 @@ VersionTuple Triple::getCanonicalVersionForOS(OSType OSKind,
19421942
}
19431943
}
19441944

1945+
Triple::CLayouts Triple::getCLayouts() const {
1946+
Triple::CLayouts Layouts;
1947+
1948+
// Default to a 32-bit RISC platform
1949+
Layouts.LongDoubleWidth = 64;
1950+
Layouts.LongDoubleAlign = 64;
1951+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1952+
1953+
enum ArchType arch = getArch();
1954+
1955+
// Keep this in sync with clang Targets.cpp AllocateTargetImpl
1956+
if (arch == arc) {
1957+
Layouts.LongDoubleAlign = 32;
1958+
} else if (arch == xcore) {
1959+
Layouts.LongDoubleAlign = 32;
1960+
} else if (arch == hexagon) {
1961+
// default configuration
1962+
} else if (arch == lanai) {
1963+
// default configuration
1964+
} else if (arch == aarch64_32 || arch == aarch64) {
1965+
Layouts.LongDoubleWidth = 128;
1966+
Layouts.LongDoubleAlign = 128;
1967+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
1968+
1969+
if (isOSWindows()) {
1970+
Layouts.LongDoubleWidth = 64;
1971+
Layouts.LongDoubleAlign = 64;
1972+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1973+
} else if (isOSDarwin()) {
1974+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 64;
1975+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1976+
}
1977+
} else if (arch == arm || arch == thumb || arch == armeb || arch == thumbeb) {
1978+
if (isOSNaCl()) {
1979+
Layouts.LongDoubleWidth = 64;
1980+
Layouts.LongDoubleAlign = 64;
1981+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1982+
} else if (isOSWindows()) {
1983+
Layouts.LongDoubleWidth = 64;
1984+
Layouts.LongDoubleAlign = 64;
1985+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1986+
}
1987+
} else if (arch == avr) {
1988+
Layouts.LongDoubleWidth = 32;
1989+
Layouts.LongDoubleAlign = 8;
1990+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEsingle();
1991+
} else if (arch == bpfeb || arch == bpfel) {
1992+
// default configuration
1993+
} else if (arch == msp430) {
1994+
Layouts.LongDoubleWidth = 64;
1995+
Layouts.LongDoubleAlign = 16;
1996+
} else if (arch == mips || arch == mipsel || arch == mips64 ||
1997+
arch == mips64el) {
1998+
if (isMIPS32()) {
1999+
// o32
2000+
Layouts.LongDoubleWidth = 64;
2001+
Layouts.LongDoubleAlign = 64;
2002+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2003+
} else {
2004+
// n32 & n64
2005+
Layouts.LongDoubleWidth = 128;
2006+
Layouts.LongDoubleAlign = 128;
2007+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2008+
if (isOSFreeBSD()) {
2009+
Layouts.LongDoubleWidth = 64;
2010+
Layouts.LongDoubleAlign = 64;
2011+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2012+
}
2013+
}
2014+
} else if (arch == m68k) {
2015+
// default configuration
2016+
} else if (arch == le32 || arch == le64) {
2017+
// default configuration
2018+
} else if (arch == ppc || arch == ppcle || arch == ppc64 || arch == ppc64le) {
2019+
Layouts.LongDoubleWidth = 128;
2020+
Layouts.LongDoubleAlign = 128;
2021+
Layouts.LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();
2022+
2023+
if (arch == ppc || arch == ppcle) {
2024+
if (isOSAIX()) {
2025+
Layouts.LongDoubleWidth = 64;
2026+
Layouts.LongDoubleAlign = 32;
2027+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2028+
} else if (isOSFreeBSD() || isOSNetBSD() || isOSOpenBSD() || isMusl()) {
2029+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 64;
2030+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2031+
}
2032+
}
2033+
} else if (arch == nvptx || arch == nvptx) {
2034+
// nvcc does not copy set long double layouts
2035+
} else if (arch == amdgcn || arch == r600) {
2036+
// default configuration
2037+
} else if (arch == riscv32 || arch == riscv64) {
2038+
Layouts.LongDoubleWidth = 128;
2039+
Layouts.LongDoubleAlign = 128;
2040+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2041+
} else if (arch == sparc || arch == sparcel) {
2042+
// default configuration
2043+
} else if (arch == sparcv9) {
2044+
Layouts.LongDoubleWidth = 128;
2045+
Layouts.LongDoubleAlign = 128;
2046+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2047+
} else if (arch == systemz) {
2048+
Layouts.LongDoubleWidth = 128;
2049+
Layouts.LongDoubleAlign = 64;
2050+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2051+
} else if (arch == tce || arch == tcele) {
2052+
Layouts.LongDoubleWidth = 32;
2053+
Layouts.LongDoubleAlign = 32;
2054+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEsingle();
2055+
} else if (arch == x86) {
2056+
Layouts.LongDoubleWidth = 96;
2057+
Layouts.LongDoubleAlign = 32;
2058+
Layouts.LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
2059+
2060+
if (isOSDarwin()) {
2061+
Layouts.LongDoubleWidth = 128;
2062+
Layouts.LongDoubleAlign = 128;
2063+
} else if (isAndroid()) {
2064+
Layouts.LongDoubleWidth = 64;
2065+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2066+
} else if (isOHOSFamily()) {
2067+
Layouts.LongDoubleWidth = 64;
2068+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2069+
} else if (isOSWindows()) {
2070+
Layouts.LongDoubleWidth = 64;
2071+
Layouts.LongDoubleAlign = 64;
2072+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2073+
2074+
if (isWindowsCygwinEnvironment()) {
2075+
Layouts.LongDoubleWidth = 64;
2076+
Layouts.LongDoubleAlign = 64;
2077+
}
2078+
} else if (isOSNaCl()) {
2079+
Layouts.LongDoubleWidth = 64;
2080+
Layouts.LongDoubleAlign = 64;
2081+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2082+
} else if (isOSIAMCU()) {
2083+
Layouts.LongDoubleWidth = 64;
2084+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2085+
}
2086+
} else if (arch == x86_64) {
2087+
Layouts.LongDoubleWidth = 128;
2088+
Layouts.LongDoubleAlign = 128;
2089+
Layouts.LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
2090+
2091+
if (isOSDarwin()) {
2092+
Layouts.LongDoubleWidth = 128;
2093+
Layouts.LongDoubleAlign = 128;
2094+
} else if (isOSLinux() && isAndroid()) {
2095+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2096+
} else if (isOSLinux() && isOHOSFamily()) {
2097+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2098+
} else if (isOSWindows()) {
2099+
Layouts.LongDoubleWidth = 64;
2100+
Layouts.LongDoubleAlign = 64;
2101+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2102+
2103+
if (isWindowsGNUEnvironment()) {
2104+
Layouts.LongDoubleWidth = 128;
2105+
Layouts.LongDoubleAlign = 128;
2106+
}
2107+
} else if (isOSNaCl()) {
2108+
Layouts.LongDoubleWidth = 64;
2109+
Layouts.LongDoubleAlign = 64;
2110+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2111+
}
2112+
} else if (arch == spir || arch == spir64 || arch == spirv ||
2113+
arch == spirv32 || arch == spirv64) {
2114+
// default configuration
2115+
} else if (arch == wasm32 || arch == wasm64) {
2116+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 128;
2117+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2118+
2119+
if (isOSEmscripten()) {
2120+
Layouts.LongDoubleAlign = 64;
2121+
}
2122+
} else if (arch == dxil) {
2123+
// default configuration
2124+
} else if (arch == renderscript32) {
2125+
// default configuration
2126+
} else if (arch == renderscript64) {
2127+
// same as aarch64 on linux
2128+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 128;
2129+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2130+
} else if (arch == ve) {
2131+
Layouts.LongDoubleWidth = 128;
2132+
Layouts.LongDoubleAlign = 128;
2133+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2134+
} else if (arch == csky) {
2135+
Layouts.LongDoubleAlign = 32;
2136+
} else if (arch == loongarch32 || arch == loongarch64) {
2137+
Layouts.LongDoubleWidth = 128;
2138+
Layouts.LongDoubleAlign = 128;
2139+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2140+
}
2141+
2142+
return Layouts;
2143+
}
2144+
19452145
// HLSL triple environment orders are relied on in the front end
19462146
static_assert(Triple::Vertex - Triple::Pixel == 1,
19472147
"incorrect HLSL stage order");

0 commit comments

Comments
 (0)