1349cc55cSDimitry Andric //===--- SPIR.cpp - Implement SPIR and SPIR-V target feature support ------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 9349cc55cSDimitry Andric // This file implements SPIR and SPIR-V TargetInfo objects. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "SPIR.h" 14*0fca6ea1SDimitry Andric #include "AMDGPU.h" 150b57cec5SDimitry Andric #include "Targets.h" 16*0fca6ea1SDimitry Andric #include "llvm/TargetParser/TargetParser.h" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric using namespace clang; 190b57cec5SDimitry Andric using namespace clang::targets; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts, 220b57cec5SDimitry Andric MacroBuilder &Builder) const { 230b57cec5SDimitry Andric DefineStd(Builder, "SPIR", Opts); 240b57cec5SDimitry Andric } 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric void SPIR32TargetInfo::getTargetDefines(const LangOptions &Opts, 270b57cec5SDimitry Andric MacroBuilder &Builder) const { 285ffd83dbSDimitry Andric SPIRTargetInfo::getTargetDefines(Opts, Builder); 290b57cec5SDimitry Andric DefineStd(Builder, "SPIR32", Opts); 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric void SPIR64TargetInfo::getTargetDefines(const LangOptions &Opts, 330b57cec5SDimitry Andric MacroBuilder &Builder) const { 345ffd83dbSDimitry Andric SPIRTargetInfo::getTargetDefines(Opts, Builder); 350b57cec5SDimitry Andric DefineStd(Builder, "SPIR64", Opts); 360b57cec5SDimitry Andric } 37349cc55cSDimitry Andric 385f757f3fSDimitry Andric void BaseSPIRVTargetInfo::getTargetDefines(const LangOptions &Opts, 39349cc55cSDimitry Andric MacroBuilder &Builder) const { 40349cc55cSDimitry Andric DefineStd(Builder, "SPIRV", Opts); 41349cc55cSDimitry Andric } 42349cc55cSDimitry Andric 435f757f3fSDimitry Andric void SPIRVTargetInfo::getTargetDefines(const LangOptions &Opts, 445f757f3fSDimitry Andric MacroBuilder &Builder) const { 455f757f3fSDimitry Andric BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); 465f757f3fSDimitry Andric } 475f757f3fSDimitry Andric 48349cc55cSDimitry Andric void SPIRV32TargetInfo::getTargetDefines(const LangOptions &Opts, 49349cc55cSDimitry Andric MacroBuilder &Builder) const { 505f757f3fSDimitry Andric BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); 51349cc55cSDimitry Andric DefineStd(Builder, "SPIRV32", Opts); 52349cc55cSDimitry Andric } 53349cc55cSDimitry Andric 54349cc55cSDimitry Andric void SPIRV64TargetInfo::getTargetDefines(const LangOptions &Opts, 55349cc55cSDimitry Andric MacroBuilder &Builder) const { 565f757f3fSDimitry Andric BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); 57349cc55cSDimitry Andric DefineStd(Builder, "SPIRV64", Opts); 58349cc55cSDimitry Andric } 59*0fca6ea1SDimitry Andric 60*0fca6ea1SDimitry Andric static const AMDGPUTargetInfo AMDGPUTI(llvm::Triple("amdgcn-amd-amdhsa"), {}); 61*0fca6ea1SDimitry Andric 62*0fca6ea1SDimitry Andric ArrayRef<const char *> SPIRV64AMDGCNTargetInfo::getGCCRegNames() const { 63*0fca6ea1SDimitry Andric return AMDGPUTI.getGCCRegNames(); 64*0fca6ea1SDimitry Andric } 65*0fca6ea1SDimitry Andric 66*0fca6ea1SDimitry Andric bool SPIRV64AMDGCNTargetInfo::initFeatureMap( 67*0fca6ea1SDimitry Andric llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef, 68*0fca6ea1SDimitry Andric const std::vector<std::string> &FeatureVec) const { 69*0fca6ea1SDimitry Andric llvm::AMDGPU::fillAMDGPUFeatureMap({}, getTriple(), Features); 70*0fca6ea1SDimitry Andric 71*0fca6ea1SDimitry Andric return TargetInfo::initFeatureMap(Features, Diags, {}, FeatureVec); 72*0fca6ea1SDimitry Andric } 73*0fca6ea1SDimitry Andric 74*0fca6ea1SDimitry Andric bool SPIRV64AMDGCNTargetInfo::validateAsmConstraint( 75*0fca6ea1SDimitry Andric const char *&Name, TargetInfo::ConstraintInfo &Info) const { 76*0fca6ea1SDimitry Andric return AMDGPUTI.validateAsmConstraint(Name, Info); 77*0fca6ea1SDimitry Andric } 78*0fca6ea1SDimitry Andric 79*0fca6ea1SDimitry Andric std::string 80*0fca6ea1SDimitry Andric SPIRV64AMDGCNTargetInfo::convertConstraint(const char *&Constraint) const { 81*0fca6ea1SDimitry Andric return AMDGPUTI.convertConstraint(Constraint); 82*0fca6ea1SDimitry Andric } 83*0fca6ea1SDimitry Andric 84*0fca6ea1SDimitry Andric ArrayRef<Builtin::Info> SPIRV64AMDGCNTargetInfo::getTargetBuiltins() const { 85*0fca6ea1SDimitry Andric return AMDGPUTI.getTargetBuiltins(); 86*0fca6ea1SDimitry Andric } 87*0fca6ea1SDimitry Andric 88*0fca6ea1SDimitry Andric void SPIRV64AMDGCNTargetInfo::getTargetDefines(const LangOptions &Opts, 89*0fca6ea1SDimitry Andric MacroBuilder &Builder) const { 90*0fca6ea1SDimitry Andric BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); 91*0fca6ea1SDimitry Andric DefineStd(Builder, "SPIRV64", Opts); 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric Builder.defineMacro("__AMD__"); 94*0fca6ea1SDimitry Andric Builder.defineMacro("__AMDGPU__"); 95*0fca6ea1SDimitry Andric Builder.defineMacro("__AMDGCN__"); 96*0fca6ea1SDimitry Andric } 97*0fca6ea1SDimitry Andric 98*0fca6ea1SDimitry Andric void SPIRV64AMDGCNTargetInfo::setAuxTarget(const TargetInfo *Aux) { 99*0fca6ea1SDimitry Andric assert(Aux && "Cannot invoke setAuxTarget without a valid auxiliary target!"); 100*0fca6ea1SDimitry Andric 101*0fca6ea1SDimitry Andric // This is a 1:1 copy of AMDGPUTargetInfo::setAuxTarget() 102*0fca6ea1SDimitry Andric assert(HalfFormat == Aux->HalfFormat); 103*0fca6ea1SDimitry Andric assert(FloatFormat == Aux->FloatFormat); 104*0fca6ea1SDimitry Andric assert(DoubleFormat == Aux->DoubleFormat); 105*0fca6ea1SDimitry Andric 106*0fca6ea1SDimitry Andric // On x86_64 long double is 80-bit extended precision format, which is 107*0fca6ea1SDimitry Andric // not supported by AMDGPU. 128-bit floating point format is also not 108*0fca6ea1SDimitry Andric // supported by AMDGPU. Therefore keep its own format for these two types. 109*0fca6ea1SDimitry Andric auto SaveLongDoubleFormat = LongDoubleFormat; 110*0fca6ea1SDimitry Andric auto SaveFloat128Format = Float128Format; 111*0fca6ea1SDimitry Andric auto SaveLongDoubleWidth = LongDoubleWidth; 112*0fca6ea1SDimitry Andric auto SaveLongDoubleAlign = LongDoubleAlign; 113*0fca6ea1SDimitry Andric copyAuxTarget(Aux); 114*0fca6ea1SDimitry Andric LongDoubleFormat = SaveLongDoubleFormat; 115*0fca6ea1SDimitry Andric Float128Format = SaveFloat128Format; 116*0fca6ea1SDimitry Andric LongDoubleWidth = SaveLongDoubleWidth; 117*0fca6ea1SDimitry Andric LongDoubleAlign = SaveLongDoubleAlign; 118*0fca6ea1SDimitry Andric // For certain builtin types support on the host target, claim they are 119*0fca6ea1SDimitry Andric // supported to pass the compilation of the host code during the device-side 120*0fca6ea1SDimitry Andric // compilation. 121*0fca6ea1SDimitry Andric // FIXME: As the side effect, we also accept `__float128` uses in the device 122*0fca6ea1SDimitry Andric // code. To reject these builtin types supported in the host target but not in 123*0fca6ea1SDimitry Andric // the device target, one approach would support `device_builtin` attribute 124*0fca6ea1SDimitry Andric // so that we could tell the device builtin types from the host ones. This 125*0fca6ea1SDimitry Andric // also solves the different representations of the same builtin type, such 126*0fca6ea1SDimitry Andric // as `size_t` in the MSVC environment. 127*0fca6ea1SDimitry Andric if (Aux->hasFloat128Type()) { 128*0fca6ea1SDimitry Andric HasFloat128 = true; 129*0fca6ea1SDimitry Andric Float128Format = DoubleFormat; 130*0fca6ea1SDimitry Andric } 131*0fca6ea1SDimitry Andric } 132