Skip to content

Commit 6843a6f

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 3140559 commit 6843a6f

File tree

5 files changed

+250
-2
lines changed

5 files changed

+250
-2
lines changed

clang/include/clang/Basic/TargetInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,10 @@ class TargetInfo : public TransferrableTargetInfo,
12741274
return Triple;
12751275
}
12761276

1277+
/// Assert that layouts for C types computed by Clang are the same as layouts
1278+
/// stored in the LLVM target.
1279+
void validateCLayouts() const;
1280+
12771281
/// Returns the target ID if supported.
12781282
virtual std::optional<std::string> getTargetID() const {
12791283
return std::nullopt;

clang/lib/Basic/TargetInfo.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,24 @@ bool TargetInfo::validatePointerAuthKey(const llvm::APSInt &value) const {
959959
return false;
960960
}
961961

962+
void TargetInfo::validateCLayouts() const {
963+
llvm::Triple::CLayouts TripleLayouts = Triple.getCLayouts(getABI());
964+
if (__builtin_expect(LongDoubleWidth != TripleLayouts.LongDoubleWidth ||
965+
LongDoubleAlign != TripleLayouts.LongDoubleAlign ||
966+
LongDoubleFormat != TripleLayouts.LongDoubleFormat,
967+
0)) {
968+
fprintf(stderr, "Clang's 'long double' width is %d, LLVM expected %d\n",
969+
LongDoubleWidth, TripleLayouts.LongDoubleWidth);
970+
fprintf(stderr, "Clang's long double' alignment is %d, LLVM expected %d\n",
971+
LongDoubleAlign, TripleLayouts.LongDoubleAlign);
972+
fprintf(
973+
stderr, "Clang's long double' format is %d, LLVM expected %d\n",
974+
llvm::APFloatBase::SemanticsToEnum(*LongDoubleFormat),
975+
llvm::APFloatBase::SemanticsToEnum(*TripleLayouts.LongDoubleFormat));
976+
llvm_unreachable("Clang & LLVM layout mismatch");
977+
}
978+
}
979+
962980
void TargetInfo::CheckFixedPointBits() const {
963981
// Check that the number of fractional and integral bits (and maybe sign) can
964982
// fit into the bits given for a fixed point type.

clang/lib/Basic/Targets.cpp

Lines changed: 13 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+
static 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

@@ -762,6 +763,16 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
762763
return std::make_unique<XtensaTargetInfo>(Triple, Opts);
763764
}
764765
}
766+
767+
std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
768+
const TargetOptions &Opts) {
769+
// Configure Clang's target and check the result against LLVM's target.
770+
std::unique_ptr<TargetInfo> target = AllocateTargetImpl(Triple, Opts);
771+
if (target != nullptr) {
772+
target->validateCLayouts();
773+
}
774+
return target;
775+
}
765776
} // namespace targets
766777
} // namespace clang
767778

llvm/include/llvm/TargetParser/Triple.h

Lines changed: 17 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

@@ -1268,6 +1269,22 @@ class Triple {
12681269
/// Returns a canonicalized OS version number for the specified OS.
12691270
static VersionTuple getCanonicalVersionForOS(OSType OSKind,
12701271
const VersionTuple &Version);
1272+
1273+
/// Layouts for C types that are relevant to libc calls generated by LLVM
1274+
struct CLayouts {
1275+
unsigned LongDoubleWidth;
1276+
unsigned LongDoubleAlign;
1277+
const fltSemantics *LongDoubleFormat;
1278+
};
1279+
1280+
/// Provide default layouts relevant to C. Frontends may override these
1281+
/// values.
1282+
CLayouts getCLayouts(const StringRef &ABIName) const;
1283+
1284+
/// Return true if `long double` and `_Float128` have the same layout.
1285+
bool isLongDoubleF128(const StringRef &ABIName) const {
1286+
return getCLayouts(ABIName).LongDoubleWidth == 128;
1287+
}
12711288
};
12721289

12731290
} // End llvm namespace

llvm/lib/TargetParser/Triple.cpp

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,6 +2164,204 @@ VersionTuple Triple::getCanonicalVersionForOS(OSType OSKind,
21642164
}
21652165
}
21662166

2167+
Triple::CLayouts Triple::getCLayouts(const StringRef &ABIName) const {
2168+
Triple::CLayouts Layouts;
2169+
2170+
// Default to a 32-bit RISC platform
2171+
Layouts.LongDoubleWidth = 64;
2172+
Layouts.LongDoubleAlign = 64;
2173+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2174+
2175+
enum ArchType Arch = getArch();
2176+
2177+
// Keep this in sync with clang Targets.cpp AllocateTargetImpl
2178+
if (Arch == arc) {
2179+
Layouts.LongDoubleAlign = 32;
2180+
} else if (Arch == xcore) {
2181+
Layouts.LongDoubleAlign = 32;
2182+
} else if (Arch == hexagon) {
2183+
// default configuration
2184+
} else if (Arch == lanai) {
2185+
// default configuration
2186+
} else if (Arch == aarch64_32 || Arch == aarch64) {
2187+
Layouts.LongDoubleWidth = 128;
2188+
Layouts.LongDoubleAlign = 128;
2189+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2190+
2191+
if (isOSWindows()) {
2192+
Layouts.LongDoubleWidth = 64;
2193+
Layouts.LongDoubleAlign = 64;
2194+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2195+
} else if (isOSDarwin()) {
2196+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 64;
2197+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2198+
}
2199+
} else if (Arch == arm || Arch == thumb || Arch == armeb || Arch == thumbeb) {
2200+
if (isOSNaCl()) {
2201+
Layouts.LongDoubleWidth = 64;
2202+
Layouts.LongDoubleAlign = 64;
2203+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2204+
} else if (isOSWindows()) {
2205+
Layouts.LongDoubleWidth = 64;
2206+
Layouts.LongDoubleAlign = 64;
2207+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2208+
}
2209+
} else if (Arch == avr) {
2210+
Layouts.LongDoubleWidth = 32;
2211+
Layouts.LongDoubleAlign = 8;
2212+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEsingle();
2213+
} else if (Arch == bpfeb || Arch == bpfel) {
2214+
// default configuration
2215+
} else if (Arch == msp430) {
2216+
Layouts.LongDoubleWidth = 64;
2217+
Layouts.LongDoubleAlign = 16;
2218+
} else if (Arch == mips || Arch == mipsel || Arch == mips64 ||
2219+
Arch == mips64el) {
2220+
if (isMIPS32()) {
2221+
// o32
2222+
Layouts.LongDoubleWidth = 64;
2223+
Layouts.LongDoubleAlign = 64;
2224+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2225+
} else {
2226+
// n32 & n64
2227+
Layouts.LongDoubleWidth = 128;
2228+
Layouts.LongDoubleAlign = 128;
2229+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2230+
if (isOSFreeBSD()) {
2231+
Layouts.LongDoubleWidth = 64;
2232+
Layouts.LongDoubleAlign = 64;
2233+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2234+
}
2235+
}
2236+
} else if (Arch == m68k) {
2237+
// default configuration
2238+
} else if (Arch == ppc || Arch == ppcle || Arch == ppc64 || Arch == ppc64le) {
2239+
Layouts.LongDoubleWidth = 128;
2240+
Layouts.LongDoubleAlign = 128;
2241+
Layouts.LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();
2242+
2243+
if (Arch == ppc || Arch == ppcle) {
2244+
if (isOSAIX()) {
2245+
Layouts.LongDoubleWidth = 64;
2246+
Layouts.LongDoubleAlign = 32;
2247+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2248+
} else if (isOSFreeBSD() || isOSNetBSD() || isOSOpenBSD() || isMusl()) {
2249+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 64;
2250+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2251+
}
2252+
}
2253+
} else if (Arch == nvptx || Arch == nvptx64) {
2254+
// nvcc does not copy set long double layouts
2255+
} else if (Arch == amdgcn || Arch == r600) {
2256+
// default configuration
2257+
} else if (Arch == riscv32 || Arch == riscv64) {
2258+
Layouts.LongDoubleWidth = 128;
2259+
Layouts.LongDoubleAlign = 128;
2260+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2261+
} else if (Arch == sparc || Arch == sparcel) {
2262+
// default configuration
2263+
} else if (Arch == sparcv9) {
2264+
Layouts.LongDoubleWidth = 128;
2265+
Layouts.LongDoubleAlign = 128;
2266+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2267+
} else if (Arch == systemz) {
2268+
Layouts.LongDoubleWidth = 128;
2269+
Layouts.LongDoubleAlign = 64;
2270+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2271+
} else if (Arch == tce || Arch == tcele) {
2272+
Layouts.LongDoubleWidth = 32;
2273+
Layouts.LongDoubleAlign = 32;
2274+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEsingle();
2275+
} else if (Arch == x86) {
2276+
Layouts.LongDoubleWidth = 96;
2277+
Layouts.LongDoubleAlign = 32;
2278+
Layouts.LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
2279+
2280+
if (isOSDarwin()) {
2281+
Layouts.LongDoubleWidth = 128;
2282+
Layouts.LongDoubleAlign = 128;
2283+
} else if (isAndroid()) {
2284+
Layouts.LongDoubleWidth = 64;
2285+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2286+
} else if (isOHOSFamily()) {
2287+
Layouts.LongDoubleWidth = 64;
2288+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2289+
} else if (isOSWindows()) {
2290+
Layouts.LongDoubleWidth = 64;
2291+
Layouts.LongDoubleAlign = 64;
2292+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2293+
2294+
if (isWindowsCygwinEnvironment()) {
2295+
Layouts.LongDoubleWidth = 64;
2296+
Layouts.LongDoubleAlign = 64;
2297+
}
2298+
} else if (isOSNaCl()) {
2299+
Layouts.LongDoubleWidth = 64;
2300+
Layouts.LongDoubleAlign = 64;
2301+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2302+
} else if (isOSIAMCU()) {
2303+
Layouts.LongDoubleWidth = 64;
2304+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2305+
}
2306+
} else if (Arch == x86_64) {
2307+
Layouts.LongDoubleWidth = 128;
2308+
Layouts.LongDoubleAlign = 128;
2309+
Layouts.LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
2310+
2311+
if (isOSDarwin()) {
2312+
Layouts.LongDoubleWidth = 128;
2313+
Layouts.LongDoubleAlign = 128;
2314+
} else if (isOSLinux() && isAndroid()) {
2315+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2316+
} else if (isOSLinux() && isOHOSFamily()) {
2317+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2318+
} else if (isOSWindows()) {
2319+
Layouts.LongDoubleWidth = 64;
2320+
Layouts.LongDoubleAlign = 64;
2321+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2322+
2323+
if (isWindowsGNUEnvironment()) {
2324+
Layouts.LongDoubleWidth = 128;
2325+
Layouts.LongDoubleAlign = 128;
2326+
}
2327+
} else if (isOSNaCl()) {
2328+
Layouts.LongDoubleWidth = 64;
2329+
Layouts.LongDoubleAlign = 64;
2330+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2331+
}
2332+
} else if (Arch == spir || Arch == spir64 || Arch == spirv ||
2333+
Arch == spirv32 || Arch == spirv64) {
2334+
// default configuration
2335+
} else if (Arch == wasm32 || Arch == wasm64) {
2336+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 128;
2337+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2338+
2339+
if (isOSEmscripten()) {
2340+
Layouts.LongDoubleAlign = 64;
2341+
}
2342+
} else if (Arch == dxil) {
2343+
// default configuration
2344+
} else if (Arch == renderscript32) {
2345+
// default configuration
2346+
} else if (Arch == renderscript64) {
2347+
// same as aarch64 on linux
2348+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 128;
2349+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2350+
} else if (Arch == ve) {
2351+
Layouts.LongDoubleWidth = 128;
2352+
Layouts.LongDoubleAlign = 128;
2353+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2354+
} else if (Arch == csky) {
2355+
Layouts.LongDoubleAlign = 32;
2356+
} else if (Arch == loongarch32 || Arch == loongarch64) {
2357+
Layouts.LongDoubleWidth = 128;
2358+
Layouts.LongDoubleAlign = 128;
2359+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2360+
}
2361+
2362+
return Layouts;
2363+
}
2364+
21672365
// HLSL triple environment orders are relied on in the front end
21682366
static_assert(Triple::Vertex - Triple::Pixel == 1,
21692367
"incorrect HLSL stage order");

0 commit comments

Comments
 (0)