1*e5dd7070Spatrick //===--- NVPTX.cpp - Implement NVPTX target feature support ---------------===// 2*e5dd7070Spatrick // 3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e5dd7070Spatrick // 7*e5dd7070Spatrick //===----------------------------------------------------------------------===// 8*e5dd7070Spatrick // 9*e5dd7070Spatrick // This file implements NVPTX TargetInfo objects. 10*e5dd7070Spatrick // 11*e5dd7070Spatrick //===----------------------------------------------------------------------===// 12*e5dd7070Spatrick 13*e5dd7070Spatrick #include "NVPTX.h" 14*e5dd7070Spatrick #include "Targets.h" 15*e5dd7070Spatrick #include "clang/Basic/Builtins.h" 16*e5dd7070Spatrick #include "clang/Basic/MacroBuilder.h" 17*e5dd7070Spatrick #include "clang/Basic/TargetBuiltins.h" 18*e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h" 19*e5dd7070Spatrick 20*e5dd7070Spatrick using namespace clang; 21*e5dd7070Spatrick using namespace clang::targets; 22*e5dd7070Spatrick 23*e5dd7070Spatrick const Builtin::Info NVPTXTargetInfo::BuiltinInfo[] = { 24*e5dd7070Spatrick #define BUILTIN(ID, TYPE, ATTRS) \ 25*e5dd7070Spatrick {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 26*e5dd7070Spatrick #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 27*e5dd7070Spatrick {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, 28*e5dd7070Spatrick #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 29*e5dd7070Spatrick {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, 30*e5dd7070Spatrick #include "clang/Basic/BuiltinsNVPTX.def" 31*e5dd7070Spatrick }; 32*e5dd7070Spatrick 33*e5dd7070Spatrick const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"}; 34*e5dd7070Spatrick 35*e5dd7070Spatrick NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple, 36*e5dd7070Spatrick const TargetOptions &Opts, 37*e5dd7070Spatrick unsigned TargetPointerWidth) 38*e5dd7070Spatrick : TargetInfo(Triple) { 39*e5dd7070Spatrick assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) && 40*e5dd7070Spatrick "NVPTX only supports 32- and 64-bit modes."); 41*e5dd7070Spatrick 42*e5dd7070Spatrick PTXVersion = 32; 43*e5dd7070Spatrick for (const StringRef Feature : Opts.FeaturesAsWritten) { 44*e5dd7070Spatrick if (!Feature.startswith("+ptx")) 45*e5dd7070Spatrick continue; 46*e5dd7070Spatrick PTXVersion = llvm::StringSwitch<unsigned>(Feature) 47*e5dd7070Spatrick .Case("+ptx64", 64) 48*e5dd7070Spatrick .Case("+ptx63", 63) 49*e5dd7070Spatrick .Case("+ptx61", 61) 50*e5dd7070Spatrick .Case("+ptx60", 60) 51*e5dd7070Spatrick .Case("+ptx50", 50) 52*e5dd7070Spatrick .Case("+ptx43", 43) 53*e5dd7070Spatrick .Case("+ptx42", 42) 54*e5dd7070Spatrick .Case("+ptx41", 41) 55*e5dd7070Spatrick .Case("+ptx40", 40) 56*e5dd7070Spatrick .Case("+ptx32", 32) 57*e5dd7070Spatrick .Default(32); 58*e5dd7070Spatrick } 59*e5dd7070Spatrick 60*e5dd7070Spatrick TLSSupported = false; 61*e5dd7070Spatrick VLASupported = false; 62*e5dd7070Spatrick AddrSpaceMap = &NVPTXAddrSpaceMap; 63*e5dd7070Spatrick UseAddrSpaceMapMangling = true; 64*e5dd7070Spatrick 65*e5dd7070Spatrick // Define available target features 66*e5dd7070Spatrick // These must be defined in sorted order! 67*e5dd7070Spatrick NoAsmVariants = true; 68*e5dd7070Spatrick GPU = CudaArch::SM_20; 69*e5dd7070Spatrick 70*e5dd7070Spatrick if (TargetPointerWidth == 32) 71*e5dd7070Spatrick resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64"); 72*e5dd7070Spatrick else if (Opts.NVPTXUseShortPointers) 73*e5dd7070Spatrick resetDataLayout( 74*e5dd7070Spatrick "e-p3:32:32-p4:32:32-p5:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64"); 75*e5dd7070Spatrick else 76*e5dd7070Spatrick resetDataLayout("e-i64:64-i128:128-v16:16-v32:32-n16:32:64"); 77*e5dd7070Spatrick 78*e5dd7070Spatrick // If possible, get a TargetInfo for our host triple, so we can match its 79*e5dd7070Spatrick // types. 80*e5dd7070Spatrick llvm::Triple HostTriple(Opts.HostTriple); 81*e5dd7070Spatrick if (!HostTriple.isNVPTX()) 82*e5dd7070Spatrick HostTarget.reset(AllocateTarget(llvm::Triple(Opts.HostTriple), Opts)); 83*e5dd7070Spatrick 84*e5dd7070Spatrick // If no host target, make some guesses about the data layout and return. 85*e5dd7070Spatrick if (!HostTarget) { 86*e5dd7070Spatrick LongWidth = LongAlign = TargetPointerWidth; 87*e5dd7070Spatrick PointerWidth = PointerAlign = TargetPointerWidth; 88*e5dd7070Spatrick switch (TargetPointerWidth) { 89*e5dd7070Spatrick case 32: 90*e5dd7070Spatrick SizeType = TargetInfo::UnsignedInt; 91*e5dd7070Spatrick PtrDiffType = TargetInfo::SignedInt; 92*e5dd7070Spatrick IntPtrType = TargetInfo::SignedInt; 93*e5dd7070Spatrick break; 94*e5dd7070Spatrick case 64: 95*e5dd7070Spatrick SizeType = TargetInfo::UnsignedLong; 96*e5dd7070Spatrick PtrDiffType = TargetInfo::SignedLong; 97*e5dd7070Spatrick IntPtrType = TargetInfo::SignedLong; 98*e5dd7070Spatrick break; 99*e5dd7070Spatrick default: 100*e5dd7070Spatrick llvm_unreachable("TargetPointerWidth must be 32 or 64"); 101*e5dd7070Spatrick } 102*e5dd7070Spatrick return; 103*e5dd7070Spatrick } 104*e5dd7070Spatrick 105*e5dd7070Spatrick // Copy properties from host target. 106*e5dd7070Spatrick PointerWidth = HostTarget->getPointerWidth(/* AddrSpace = */ 0); 107*e5dd7070Spatrick PointerAlign = HostTarget->getPointerAlign(/* AddrSpace = */ 0); 108*e5dd7070Spatrick BoolWidth = HostTarget->getBoolWidth(); 109*e5dd7070Spatrick BoolAlign = HostTarget->getBoolAlign(); 110*e5dd7070Spatrick IntWidth = HostTarget->getIntWidth(); 111*e5dd7070Spatrick IntAlign = HostTarget->getIntAlign(); 112*e5dd7070Spatrick HalfWidth = HostTarget->getHalfWidth(); 113*e5dd7070Spatrick HalfAlign = HostTarget->getHalfAlign(); 114*e5dd7070Spatrick FloatWidth = HostTarget->getFloatWidth(); 115*e5dd7070Spatrick FloatAlign = HostTarget->getFloatAlign(); 116*e5dd7070Spatrick DoubleWidth = HostTarget->getDoubleWidth(); 117*e5dd7070Spatrick DoubleAlign = HostTarget->getDoubleAlign(); 118*e5dd7070Spatrick LongWidth = HostTarget->getLongWidth(); 119*e5dd7070Spatrick LongAlign = HostTarget->getLongAlign(); 120*e5dd7070Spatrick LongLongWidth = HostTarget->getLongLongWidth(); 121*e5dd7070Spatrick LongLongAlign = HostTarget->getLongLongAlign(); 122*e5dd7070Spatrick MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0); 123*e5dd7070Spatrick NewAlign = HostTarget->getNewAlign(); 124*e5dd7070Spatrick DefaultAlignForAttributeAligned = 125*e5dd7070Spatrick HostTarget->getDefaultAlignForAttributeAligned(); 126*e5dd7070Spatrick SizeType = HostTarget->getSizeType(); 127*e5dd7070Spatrick IntMaxType = HostTarget->getIntMaxType(); 128*e5dd7070Spatrick PtrDiffType = HostTarget->getPtrDiffType(/* AddrSpace = */ 0); 129*e5dd7070Spatrick IntPtrType = HostTarget->getIntPtrType(); 130*e5dd7070Spatrick WCharType = HostTarget->getWCharType(); 131*e5dd7070Spatrick WIntType = HostTarget->getWIntType(); 132*e5dd7070Spatrick Char16Type = HostTarget->getChar16Type(); 133*e5dd7070Spatrick Char32Type = HostTarget->getChar32Type(); 134*e5dd7070Spatrick Int64Type = HostTarget->getInt64Type(); 135*e5dd7070Spatrick SigAtomicType = HostTarget->getSigAtomicType(); 136*e5dd7070Spatrick ProcessIDType = HostTarget->getProcessIDType(); 137*e5dd7070Spatrick 138*e5dd7070Spatrick UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment(); 139*e5dd7070Spatrick UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment(); 140*e5dd7070Spatrick UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment(); 141*e5dd7070Spatrick ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary(); 142*e5dd7070Spatrick 143*e5dd7070Spatrick // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and 144*e5dd7070Spatrick // we need those macros to be identical on host and device, because (among 145*e5dd7070Spatrick // other things) they affect which standard library classes are defined, and 146*e5dd7070Spatrick // we need all classes to be defined on both the host and device. 147*e5dd7070Spatrick MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth(); 148*e5dd7070Spatrick 149*e5dd7070Spatrick // Properties intentionally not copied from host: 150*e5dd7070Spatrick // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the 151*e5dd7070Spatrick // host/device boundary. 152*e5dd7070Spatrick // - SuitableAlign: Not visible across the host/device boundary, and may 153*e5dd7070Spatrick // correctly be different on host/device, e.g. if host has wider vector 154*e5dd7070Spatrick // types than device. 155*e5dd7070Spatrick // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same 156*e5dd7070Spatrick // as its double type, but that's not necessarily true on the host. 157*e5dd7070Spatrick // TODO: nvcc emits a warning when using long double on device; we should 158*e5dd7070Spatrick // do the same. 159*e5dd7070Spatrick } 160*e5dd7070Spatrick 161*e5dd7070Spatrick ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const { 162*e5dd7070Spatrick return llvm::makeArrayRef(GCCRegNames); 163*e5dd7070Spatrick } 164*e5dd7070Spatrick 165*e5dd7070Spatrick bool NVPTXTargetInfo::hasFeature(StringRef Feature) const { 166*e5dd7070Spatrick return llvm::StringSwitch<bool>(Feature) 167*e5dd7070Spatrick .Cases("ptx", "nvptx", true) 168*e5dd7070Spatrick .Default(false); 169*e5dd7070Spatrick } 170*e5dd7070Spatrick 171*e5dd7070Spatrick void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts, 172*e5dd7070Spatrick MacroBuilder &Builder) const { 173*e5dd7070Spatrick Builder.defineMacro("__PTX__"); 174*e5dd7070Spatrick Builder.defineMacro("__NVPTX__"); 175*e5dd7070Spatrick if (Opts.CUDAIsDevice) { 176*e5dd7070Spatrick // Set __CUDA_ARCH__ for the GPU specified. 177*e5dd7070Spatrick std::string CUDAArchCode = [this] { 178*e5dd7070Spatrick switch (GPU) { 179*e5dd7070Spatrick case CudaArch::GFX600: 180*e5dd7070Spatrick case CudaArch::GFX601: 181*e5dd7070Spatrick case CudaArch::GFX700: 182*e5dd7070Spatrick case CudaArch::GFX701: 183*e5dd7070Spatrick case CudaArch::GFX702: 184*e5dd7070Spatrick case CudaArch::GFX703: 185*e5dd7070Spatrick case CudaArch::GFX704: 186*e5dd7070Spatrick case CudaArch::GFX801: 187*e5dd7070Spatrick case CudaArch::GFX802: 188*e5dd7070Spatrick case CudaArch::GFX803: 189*e5dd7070Spatrick case CudaArch::GFX810: 190*e5dd7070Spatrick case CudaArch::GFX900: 191*e5dd7070Spatrick case CudaArch::GFX902: 192*e5dd7070Spatrick case CudaArch::GFX904: 193*e5dd7070Spatrick case CudaArch::GFX906: 194*e5dd7070Spatrick case CudaArch::GFX908: 195*e5dd7070Spatrick case CudaArch::GFX909: 196*e5dd7070Spatrick case CudaArch::GFX1010: 197*e5dd7070Spatrick case CudaArch::GFX1011: 198*e5dd7070Spatrick case CudaArch::GFX1012: 199*e5dd7070Spatrick case CudaArch::LAST: 200*e5dd7070Spatrick break; 201*e5dd7070Spatrick case CudaArch::UNKNOWN: 202*e5dd7070Spatrick assert(false && "No GPU arch when compiling CUDA device code."); 203*e5dd7070Spatrick return ""; 204*e5dd7070Spatrick case CudaArch::SM_20: 205*e5dd7070Spatrick return "200"; 206*e5dd7070Spatrick case CudaArch::SM_21: 207*e5dd7070Spatrick return "210"; 208*e5dd7070Spatrick case CudaArch::SM_30: 209*e5dd7070Spatrick return "300"; 210*e5dd7070Spatrick case CudaArch::SM_32: 211*e5dd7070Spatrick return "320"; 212*e5dd7070Spatrick case CudaArch::SM_35: 213*e5dd7070Spatrick return "350"; 214*e5dd7070Spatrick case CudaArch::SM_37: 215*e5dd7070Spatrick return "370"; 216*e5dd7070Spatrick case CudaArch::SM_50: 217*e5dd7070Spatrick return "500"; 218*e5dd7070Spatrick case CudaArch::SM_52: 219*e5dd7070Spatrick return "520"; 220*e5dd7070Spatrick case CudaArch::SM_53: 221*e5dd7070Spatrick return "530"; 222*e5dd7070Spatrick case CudaArch::SM_60: 223*e5dd7070Spatrick return "600"; 224*e5dd7070Spatrick case CudaArch::SM_61: 225*e5dd7070Spatrick return "610"; 226*e5dd7070Spatrick case CudaArch::SM_62: 227*e5dd7070Spatrick return "620"; 228*e5dd7070Spatrick case CudaArch::SM_70: 229*e5dd7070Spatrick return "700"; 230*e5dd7070Spatrick case CudaArch::SM_72: 231*e5dd7070Spatrick return "720"; 232*e5dd7070Spatrick case CudaArch::SM_75: 233*e5dd7070Spatrick return "750"; 234*e5dd7070Spatrick } 235*e5dd7070Spatrick llvm_unreachable("unhandled CudaArch"); 236*e5dd7070Spatrick }(); 237*e5dd7070Spatrick Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode); 238*e5dd7070Spatrick } 239*e5dd7070Spatrick } 240*e5dd7070Spatrick 241*e5dd7070Spatrick ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const { 242*e5dd7070Spatrick return llvm::makeArrayRef(BuiltinInfo, clang::NVPTX::LastTSBuiltin - 243*e5dd7070Spatrick Builtin::FirstTSBuiltin); 244*e5dd7070Spatrick } 245