1 //===--- SPIR.cpp - Implement SPIR and SPIR-V target feature support ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements SPIR and SPIR-V TargetInfo objects. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "SPIR.h" 14 #include "AMDGPU.h" 15 #include "Targets.h" 16 #include "llvm/TargetParser/TargetParser.h" 17 18 using namespace clang; 19 using namespace clang::targets; 20 21 void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts, 22 MacroBuilder &Builder) const { 23 DefineStd(Builder, "SPIR", Opts); 24 } 25 26 void SPIR32TargetInfo::getTargetDefines(const LangOptions &Opts, 27 MacroBuilder &Builder) const { 28 SPIRTargetInfo::getTargetDefines(Opts, Builder); 29 DefineStd(Builder, "SPIR32", Opts); 30 } 31 32 void SPIR64TargetInfo::getTargetDefines(const LangOptions &Opts, 33 MacroBuilder &Builder) const { 34 SPIRTargetInfo::getTargetDefines(Opts, Builder); 35 DefineStd(Builder, "SPIR64", Opts); 36 } 37 38 void BaseSPIRVTargetInfo::getTargetDefines(const LangOptions &Opts, 39 MacroBuilder &Builder) const { 40 DefineStd(Builder, "SPIRV", Opts); 41 } 42 43 void SPIRVTargetInfo::getTargetDefines(const LangOptions &Opts, 44 MacroBuilder &Builder) const { 45 BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); 46 } 47 48 void SPIRV32TargetInfo::getTargetDefines(const LangOptions &Opts, 49 MacroBuilder &Builder) const { 50 BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); 51 DefineStd(Builder, "SPIRV32", Opts); 52 } 53 54 void SPIRV64TargetInfo::getTargetDefines(const LangOptions &Opts, 55 MacroBuilder &Builder) const { 56 BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); 57 DefineStd(Builder, "SPIRV64", Opts); 58 } 59 60 static const AMDGPUTargetInfo AMDGPUTI(llvm::Triple("amdgcn-amd-amdhsa"), {}); 61 62 ArrayRef<const char *> SPIRV64AMDGCNTargetInfo::getGCCRegNames() const { 63 return AMDGPUTI.getGCCRegNames(); 64 } 65 66 bool SPIRV64AMDGCNTargetInfo::initFeatureMap( 67 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef, 68 const std::vector<std::string> &FeatureVec) const { 69 llvm::AMDGPU::fillAMDGPUFeatureMap({}, getTriple(), Features); 70 71 return TargetInfo::initFeatureMap(Features, Diags, {}, FeatureVec); 72 } 73 74 bool SPIRV64AMDGCNTargetInfo::validateAsmConstraint( 75 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 76 return AMDGPUTI.validateAsmConstraint(Name, Info); 77 } 78 79 std::string 80 SPIRV64AMDGCNTargetInfo::convertConstraint(const char *&Constraint) const { 81 return AMDGPUTI.convertConstraint(Constraint); 82 } 83 84 ArrayRef<Builtin::Info> SPIRV64AMDGCNTargetInfo::getTargetBuiltins() const { 85 return AMDGPUTI.getTargetBuiltins(); 86 } 87 88 void SPIRV64AMDGCNTargetInfo::getTargetDefines(const LangOptions &Opts, 89 MacroBuilder &Builder) const { 90 BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); 91 DefineStd(Builder, "SPIRV64", Opts); 92 93 Builder.defineMacro("__AMD__"); 94 Builder.defineMacro("__AMDGPU__"); 95 Builder.defineMacro("__AMDGCN__"); 96 } 97 98 void SPIRV64AMDGCNTargetInfo::setAuxTarget(const TargetInfo *Aux) { 99 assert(Aux && "Cannot invoke setAuxTarget without a valid auxiliary target!"); 100 101 // This is a 1:1 copy of AMDGPUTargetInfo::setAuxTarget() 102 assert(HalfFormat == Aux->HalfFormat); 103 assert(FloatFormat == Aux->FloatFormat); 104 assert(DoubleFormat == Aux->DoubleFormat); 105 106 // On x86_64 long double is 80-bit extended precision format, which is 107 // not supported by AMDGPU. 128-bit floating point format is also not 108 // supported by AMDGPU. Therefore keep its own format for these two types. 109 auto SaveLongDoubleFormat = LongDoubleFormat; 110 auto SaveFloat128Format = Float128Format; 111 auto SaveLongDoubleWidth = LongDoubleWidth; 112 auto SaveLongDoubleAlign = LongDoubleAlign; 113 copyAuxTarget(Aux); 114 LongDoubleFormat = SaveLongDoubleFormat; 115 Float128Format = SaveFloat128Format; 116 LongDoubleWidth = SaveLongDoubleWidth; 117 LongDoubleAlign = SaveLongDoubleAlign; 118 // For certain builtin types support on the host target, claim they are 119 // supported to pass the compilation of the host code during the device-side 120 // compilation. 121 // FIXME: As the side effect, we also accept `__float128` uses in the device 122 // code. To reject these builtin types supported in the host target but not in 123 // the device target, one approach would support `device_builtin` attribute 124 // so that we could tell the device builtin types from the host ones. This 125 // also solves the different representations of the same builtin type, such 126 // as `size_t` in the MSVC environment. 127 if (Aux->hasFloat128Type()) { 128 HasFloat128 = true; 129 Float128Format = DoubleFormat; 130 } 131 } 132