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 TLSSupported = false; 44 VLASupported = false; 45 AddrSpaceMap = &NVPTXAddrSpaceMap; 46 UseAddrSpaceMapMangling = true; 47 48 // Define available target features 49 // These must be defined in sorted order! 50 NoAsmVariants = true; 51 GPU = CudaArch::SM_20; 52 53 if (TargetPointerWidth == 32) 54 resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64"); 55 else 56 resetDataLayout("e-i64:64-i128:128-v16:16-v32:32-n16:32:64"); 57 58 // If possible, get a TargetInfo for our host triple, so we can match its 59 // types. 60 llvm::Triple HostTriple(Opts.HostTriple); 61 if (!HostTriple.isNVPTX()) 62 HostTarget.reset(AllocateTarget(llvm::Triple(Opts.HostTriple), Opts)); 63 64 // If no host target, make some guesses about the data layout and return. 65 if (!HostTarget) { 66 LongWidth = LongAlign = TargetPointerWidth; 67 PointerWidth = PointerAlign = TargetPointerWidth; 68 switch (TargetPointerWidth) { 69 case 32: 70 SizeType = TargetInfo::UnsignedInt; 71 PtrDiffType = TargetInfo::SignedInt; 72 IntPtrType = TargetInfo::SignedInt; 73 break; 74 case 64: 75 SizeType = TargetInfo::UnsignedLong; 76 PtrDiffType = TargetInfo::SignedLong; 77 IntPtrType = TargetInfo::SignedLong; 78 break; 79 default: 80 llvm_unreachable("TargetPointerWidth must be 32 or 64"); 81 } 82 return; 83 } 84 85 // Copy properties from host target. 86 PointerWidth = HostTarget->getPointerWidth(/* AddrSpace = */ 0); 87 PointerAlign = HostTarget->getPointerAlign(/* AddrSpace = */ 0); 88 BoolWidth = HostTarget->getBoolWidth(); 89 BoolAlign = HostTarget->getBoolAlign(); 90 IntWidth = HostTarget->getIntWidth(); 91 IntAlign = HostTarget->getIntAlign(); 92 HalfWidth = HostTarget->getHalfWidth(); 93 HalfAlign = HostTarget->getHalfAlign(); 94 FloatWidth = HostTarget->getFloatWidth(); 95 FloatAlign = HostTarget->getFloatAlign(); 96 DoubleWidth = HostTarget->getDoubleWidth(); 97 DoubleAlign = HostTarget->getDoubleAlign(); 98 LongWidth = HostTarget->getLongWidth(); 99 LongAlign = HostTarget->getLongAlign(); 100 LongLongWidth = HostTarget->getLongLongWidth(); 101 LongLongAlign = HostTarget->getLongLongAlign(); 102 MinGlobalAlign = HostTarget->getMinGlobalAlign(); 103 NewAlign = HostTarget->getNewAlign(); 104 DefaultAlignForAttributeAligned = 105 HostTarget->getDefaultAlignForAttributeAligned(); 106 SizeType = HostTarget->getSizeType(); 107 IntMaxType = HostTarget->getIntMaxType(); 108 PtrDiffType = HostTarget->getPtrDiffType(/* AddrSpace = */ 0); 109 IntPtrType = HostTarget->getIntPtrType(); 110 WCharType = HostTarget->getWCharType(); 111 WIntType = HostTarget->getWIntType(); 112 Char16Type = HostTarget->getChar16Type(); 113 Char32Type = HostTarget->getChar32Type(); 114 Int64Type = HostTarget->getInt64Type(); 115 SigAtomicType = HostTarget->getSigAtomicType(); 116 ProcessIDType = HostTarget->getProcessIDType(); 117 118 UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment(); 119 UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment(); 120 UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment(); 121 ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary(); 122 123 // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and 124 // we need those macros to be identical on host and device, because (among 125 // other things) they affect which standard library classes are defined, and 126 // we need all classes to be defined on both the host and device. 127 MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth(); 128 129 // Properties intentionally not copied from host: 130 // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the 131 // host/device boundary. 132 // - SuitableAlign: Not visible across the host/device boundary, and may 133 // correctly be different on host/device, e.g. if host has wider vector 134 // types than device. 135 // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same 136 // as its double type, but that's not necessarily true on the host. 137 // TODO: nvcc emits a warning when using long double on device; we should 138 // do the same. 139 } 140 141 ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const { 142 return llvm::makeArrayRef(GCCRegNames); 143 } 144 145 bool NVPTXTargetInfo::hasFeature(StringRef Feature) const { 146 return llvm::StringSwitch<bool>(Feature) 147 .Cases("ptx", "nvptx", true) 148 .Case("satom", GPU >= CudaArch::SM_60) // Atomics w/ scope. 149 .Default(false); 150 } 151 152 void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts, 153 MacroBuilder &Builder) const { 154 Builder.defineMacro("__PTX__"); 155 Builder.defineMacro("__NVPTX__"); 156 if (Opts.CUDAIsDevice) { 157 // Set __CUDA_ARCH__ for the GPU specified. 158 std::string CUDAArchCode = [this] { 159 switch (GPU) { 160 case CudaArch::LAST: 161 break; 162 case CudaArch::UNKNOWN: 163 assert(false && "No GPU arch when compiling CUDA device code."); 164 return ""; 165 case CudaArch::SM_20: 166 return "200"; 167 case CudaArch::SM_21: 168 return "210"; 169 case CudaArch::SM_30: 170 return "300"; 171 case CudaArch::SM_32: 172 return "320"; 173 case CudaArch::SM_35: 174 return "350"; 175 case CudaArch::SM_37: 176 return "370"; 177 case CudaArch::SM_50: 178 return "500"; 179 case CudaArch::SM_52: 180 return "520"; 181 case CudaArch::SM_53: 182 return "530"; 183 case CudaArch::SM_60: 184 return "600"; 185 case CudaArch::SM_61: 186 return "610"; 187 case CudaArch::SM_62: 188 return "620"; 189 case CudaArch::SM_70: 190 return "700"; 191 case CudaArch::SM_72: 192 return "720"; 193 } 194 llvm_unreachable("unhandled CudaArch"); 195 }(); 196 Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode); 197 } 198 } 199 200 ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const { 201 return llvm::makeArrayRef(BuiltinInfo, clang::NVPTX::LastTSBuiltin - 202 Builtin::FirstTSBuiltin); 203 } 204