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