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