xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/SPIR.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
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 "clang/Basic/MacroBuilder.h"
16 #include "clang/Basic/TargetBuiltins.h"
17 #include "llvm/TargetParser/TargetParser.h"
18 
19 using namespace clang;
20 using namespace clang::targets;
21 
22 static constexpr int NumBuiltins =
23     clang::SPIRV::LastTSBuiltin - Builtin::FirstTSBuiltin;
24 
25 #define GET_BUILTIN_STR_TABLE
26 #include "clang/Basic/BuiltinsSPIRVCommon.inc"
27 #undef GET_BUILTIN_STR_TABLE
28 
29 static constexpr Builtin::Info BuiltinInfos[] = {
30 #define GET_BUILTIN_INFOS
31 #include "clang/Basic/BuiltinsSPIRVCommon.inc"
32 #undef GET_BUILTIN_INFOS
33 };
34 
35 namespace CL {
36 #define GET_BUILTIN_STR_TABLE
37 #include "clang/Basic/BuiltinsSPIRVCL.inc"
38 #undef GET_BUILTIN_STR_TABLE
39 
40 static constexpr Builtin::Info BuiltinInfos[] = {
41 #define GET_BUILTIN_INFOS
42 #include "clang/Basic/BuiltinsSPIRVCL.inc"
43 #undef GET_BUILTIN_INFOS
44 };
45 } // namespace CL
46 
47 namespace VK {
48 #define GET_BUILTIN_STR_TABLE
49 #include "clang/Basic/BuiltinsSPIRVVK.inc"
50 #undef GET_BUILTIN_STR_TABLE
51 
52 static constexpr Builtin::Info BuiltinInfos[] = {
53 #define GET_BUILTIN_INFOS
54 #include "clang/Basic/BuiltinsSPIRVVK.inc"
55 #undef GET_BUILTIN_INFOS
56 };
57 } // namespace VK
58 
59 static_assert(std::size(BuiltinInfos) + std::size(CL::BuiltinInfos) +
60                   std::size(VK::BuiltinInfos) ==
61               NumBuiltins);
62 
63 llvm::SmallVector<Builtin::InfosShard>
64 BaseSPIRVTargetInfo::getTargetBuiltins() const {
65   return {{&BuiltinStrings, BuiltinInfos},
66           {&VK::BuiltinStrings, VK::BuiltinInfos},
67           {&CL::BuiltinStrings, CL::BuiltinInfos}};
68 }
69 
70 void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts,
71                                       MacroBuilder &Builder) const {
72   DefineStd(Builder, "SPIR", Opts);
73 }
74 
75 void SPIR32TargetInfo::getTargetDefines(const LangOptions &Opts,
76                                         MacroBuilder &Builder) const {
77   SPIRTargetInfo::getTargetDefines(Opts, Builder);
78   DefineStd(Builder, "SPIR32", Opts);
79 }
80 
81 void SPIR64TargetInfo::getTargetDefines(const LangOptions &Opts,
82                                         MacroBuilder &Builder) const {
83   SPIRTargetInfo::getTargetDefines(Opts, Builder);
84   DefineStd(Builder, "SPIR64", Opts);
85 }
86 
87 void BaseSPIRVTargetInfo::getTargetDefines(const LangOptions &Opts,
88                                            MacroBuilder &Builder) const {
89   DefineStd(Builder, "SPIRV", Opts);
90   if (Opts.HLSL)
91     DefineStd(Builder, "spirv", Opts);
92 }
93 
94 void SPIRVTargetInfo::getTargetDefines(const LangOptions &Opts,
95                                        MacroBuilder &Builder) const {
96   BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder);
97 }
98 
99 void SPIRV32TargetInfo::getTargetDefines(const LangOptions &Opts,
100                                          MacroBuilder &Builder) const {
101   BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder);
102   DefineStd(Builder, "SPIRV32", Opts);
103 }
104 
105 void SPIRV64TargetInfo::getTargetDefines(const LangOptions &Opts,
106                                          MacroBuilder &Builder) const {
107   BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder);
108   DefineStd(Builder, "SPIRV64", Opts);
109 }
110 
111 static const AMDGPUTargetInfo AMDGPUTI(llvm::Triple("amdgcn-amd-amdhsa"), {});
112 
113 ArrayRef<const char *> SPIRV64AMDGCNTargetInfo::getGCCRegNames() const {
114   return AMDGPUTI.getGCCRegNames();
115 }
116 
117 bool SPIRV64AMDGCNTargetInfo::initFeatureMap(
118     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef,
119     const std::vector<std::string> &FeatureVec) const {
120   llvm::AMDGPU::fillAMDGPUFeatureMap({}, getTriple(), Features);
121 
122   return TargetInfo::initFeatureMap(Features, Diags, {}, FeatureVec);
123 }
124 
125 bool SPIRV64AMDGCNTargetInfo::validateAsmConstraint(
126     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
127   return AMDGPUTI.validateAsmConstraint(Name, Info);
128 }
129 
130 std::string
131 SPIRV64AMDGCNTargetInfo::convertConstraint(const char *&Constraint) const {
132   return AMDGPUTI.convertConstraint(Constraint);
133 }
134 
135 llvm::SmallVector<Builtin::InfosShard>
136 SPIRV64AMDGCNTargetInfo::getTargetBuiltins() const {
137   return AMDGPUTI.getTargetBuiltins();
138 }
139 
140 void SPIRV64AMDGCNTargetInfo::getTargetDefines(const LangOptions &Opts,
141                                                MacroBuilder &Builder) const {
142   BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder);
143   DefineStd(Builder, "SPIRV64", Opts);
144 
145   Builder.defineMacro("__AMD__");
146   Builder.defineMacro("__AMDGPU__");
147   Builder.defineMacro("__AMDGCN__");
148 }
149 
150 void SPIRV64AMDGCNTargetInfo::setAuxTarget(const TargetInfo *Aux) {
151   assert(Aux && "Cannot invoke setAuxTarget without a valid auxiliary target!");
152 
153   // This is a 1:1 copy of AMDGPUTargetInfo::setAuxTarget()
154   assert(HalfFormat == Aux->HalfFormat);
155   assert(FloatFormat == Aux->FloatFormat);
156   assert(DoubleFormat == Aux->DoubleFormat);
157 
158   // On x86_64 long double is 80-bit extended precision format, which is
159   // not supported by AMDGPU. 128-bit floating point format is also not
160   // supported by AMDGPU. Therefore keep its own format for these two types.
161   auto SaveLongDoubleFormat = LongDoubleFormat;
162   auto SaveFloat128Format = Float128Format;
163   auto SaveLongDoubleWidth = LongDoubleWidth;
164   auto SaveLongDoubleAlign = LongDoubleAlign;
165   copyAuxTarget(Aux);
166   LongDoubleFormat = SaveLongDoubleFormat;
167   Float128Format = SaveFloat128Format;
168   LongDoubleWidth = SaveLongDoubleWidth;
169   LongDoubleAlign = SaveLongDoubleAlign;
170   // For certain builtin types support on the host target, claim they are
171   // supported to pass the compilation of the host code during the device-side
172   // compilation.
173   // FIXME: As the side effect, we also accept `__float128` uses in the device
174   // code. To reject these builtin types supported in the host target but not in
175   // the device target, one approach would support `device_builtin` attribute
176   // so that we could tell the device builtin types from the host ones. This
177   // also solves the different representations of the same builtin type, such
178   // as `size_t` in the MSVC environment.
179   if (Aux->hasFloat128Type()) {
180     HasFloat128 = true;
181     Float128Format = DoubleFormat;
182   }
183 }
184