Skip to content

Commit a0c33d3

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 f110337 commit a0c33d3

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
@@ -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();
964+
if (__builtin_expect(LongDoubleWidth != TripleLayouts.LongDoubleWidth ||
965+
LongDoubleAlign != TripleLayouts.LongDoubleAlign ||
966+
LongDoubleFormat != TripleLayouts.LongDoubleFormat,
967+
0)) {
968+
fprintf(stderr, "'long double' width got %d, expected %d\n",
969+
LongDoubleWidth, TripleLayouts.LongDoubleWidth);
970+
fprintf(stderr, "'long double' align got %d, expected %d\n",
971+
LongDoubleAlign, TripleLayouts.LongDoubleAlign);
972+
fprintf(
973+
stderr, "'long double' format got %d, 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: 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

@@ -762,6 +763,15 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
762763
return std::make_unique<XtensaTargetInfo>(Triple, Opts);
763764
}
764765
}
766+
std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
767+
const TargetOptions &Opts) {
768+
769+
std::unique_ptr<TargetInfo> target = AllocateTargetImpl(Triple, Opts);
770+
if (target != nullptr) {
771+
target->validateCLayouts();
772+
}
773+
return target;
774+
}
765775
} // namespace targets
766776
} // namespace clang
767777

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

@@ -1268,6 +1269,23 @@ 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 char LongDoubleWidth;
1276+
unsigned char LongDoubleAlign;
1277+
const fltSemantics *LongDoubleFormat;
1278+
};
1279+
1280+
/// Provide default layouts relevant to C. Frontends may override these
1281+
/// values.
1282+
CLayouts getCLayouts() const;
1283+
1284+
/// Return true if `long double` and `__float128` have the same layout.
1285+
bool isLongDoubleF128() const {
1286+
// TODO: do we also need to check alignment?
1287+
return getCLayouts().LongDoubleWidth == 128;
1288+
}
12711289
};
12721290

12731291
} // End llvm namespace

llvm/lib/TargetParser/Triple.cpp

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

2167+
Triple::CLayouts Triple::getCLayouts() 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 == le32 || arch == le64) {
2239+
// default configuration
2240+
} else if (arch == ppc || arch == ppcle || arch == ppc64 || arch == ppc64le) {
2241+
Layouts.LongDoubleWidth = 128;
2242+
Layouts.LongDoubleAlign = 128;
2243+
Layouts.LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();
2244+
2245+
if (arch == ppc || arch == ppcle) {
2246+
if (isOSAIX()) {
2247+
Layouts.LongDoubleWidth = 64;
2248+
Layouts.LongDoubleAlign = 32;
2249+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2250+
} else if (isOSFreeBSD() || isOSNetBSD() || isOSOpenBSD() || isMusl()) {
2251+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 64;
2252+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2253+
}
2254+
}
2255+
} else if (arch == nvptx || arch == nvptx) {
2256+
// nvcc does not copy set long double layouts
2257+
} else if (arch == amdgcn || arch == r600) {
2258+
// default configuration
2259+
} else if (arch == riscv32 || arch == riscv64) {
2260+
Layouts.LongDoubleWidth = 128;
2261+
Layouts.LongDoubleAlign = 128;
2262+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2263+
} else if (arch == sparc || arch == sparcel) {
2264+
// default configuration
2265+
} else if (arch == sparcv9) {
2266+
Layouts.LongDoubleWidth = 128;
2267+
Layouts.LongDoubleAlign = 128;
2268+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2269+
} else if (arch == systemz) {
2270+
Layouts.LongDoubleWidth = 128;
2271+
Layouts.LongDoubleAlign = 64;
2272+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2273+
} else if (arch == tce || arch == tcele) {
2274+
Layouts.LongDoubleWidth = 32;
2275+
Layouts.LongDoubleAlign = 32;
2276+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEsingle();
2277+
} else if (arch == x86) {
2278+
Layouts.LongDoubleWidth = 96;
2279+
Layouts.LongDoubleAlign = 32;
2280+
Layouts.LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
2281+
2282+
if (isOSDarwin()) {
2283+
Layouts.LongDoubleWidth = 128;
2284+
Layouts.LongDoubleAlign = 128;
2285+
} else if (isAndroid()) {
2286+
Layouts.LongDoubleWidth = 64;
2287+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2288+
} else if (isOHOSFamily()) {
2289+
Layouts.LongDoubleWidth = 64;
2290+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2291+
} else if (isOSWindows()) {
2292+
Layouts.LongDoubleWidth = 64;
2293+
Layouts.LongDoubleAlign = 64;
2294+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2295+
2296+
if (isWindowsCygwinEnvironment()) {
2297+
Layouts.LongDoubleWidth = 64;
2298+
Layouts.LongDoubleAlign = 64;
2299+
}
2300+
} else if (isOSNaCl()) {
2301+
Layouts.LongDoubleWidth = 64;
2302+
Layouts.LongDoubleAlign = 64;
2303+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2304+
} else if (isOSIAMCU()) {
2305+
Layouts.LongDoubleWidth = 64;
2306+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2307+
}
2308+
} else if (arch == x86_64) {
2309+
Layouts.LongDoubleWidth = 128;
2310+
Layouts.LongDoubleAlign = 128;
2311+
Layouts.LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
2312+
2313+
if (isOSDarwin()) {
2314+
Layouts.LongDoubleWidth = 128;
2315+
Layouts.LongDoubleAlign = 128;
2316+
} else if (isOSLinux() && isAndroid()) {
2317+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2318+
} else if (isOSLinux() && isOHOSFamily()) {
2319+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2320+
} else if (isOSWindows()) {
2321+
Layouts.LongDoubleWidth = 64;
2322+
Layouts.LongDoubleAlign = 64;
2323+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2324+
2325+
if (isWindowsGNUEnvironment()) {
2326+
Layouts.LongDoubleWidth = 128;
2327+
Layouts.LongDoubleAlign = 128;
2328+
}
2329+
} else if (isOSNaCl()) {
2330+
Layouts.LongDoubleWidth = 64;
2331+
Layouts.LongDoubleAlign = 64;
2332+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEdouble();
2333+
}
2334+
} else if (arch == spir || arch == spir64 || arch == spirv ||
2335+
arch == spirv32 || arch == spirv64) {
2336+
// default configuration
2337+
} else if (arch == wasm32 || arch == wasm64) {
2338+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 128;
2339+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2340+
2341+
if (isOSEmscripten()) {
2342+
Layouts.LongDoubleAlign = 64;
2343+
}
2344+
} else if (arch == dxil) {
2345+
// default configuration
2346+
} else if (arch == renderscript32) {
2347+
// default configuration
2348+
} else if (arch == renderscript64) {
2349+
// same as aarch64 on linux
2350+
Layouts.LongDoubleWidth = Layouts.LongDoubleAlign = 128;
2351+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2352+
} else if (arch == ve) {
2353+
Layouts.LongDoubleWidth = 128;
2354+
Layouts.LongDoubleAlign = 128;
2355+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2356+
} else if (arch == csky) {
2357+
Layouts.LongDoubleAlign = 32;
2358+
} else if (arch == loongarch32 || arch == loongarch64) {
2359+
Layouts.LongDoubleWidth = 128;
2360+
Layouts.LongDoubleAlign = 128;
2361+
Layouts.LongDoubleFormat = &llvm::APFloat::IEEEquad();
2362+
}
2363+
2364+
return Layouts;
2365+
}
2366+
21672367
// HLSL triple environment orders are relied on in the front end
21682368
static_assert(Triple::Vertex - Triple::Pixel == 1,
21692369
"incorrect HLSL stage order");

0 commit comments

Comments
 (0)