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, MacroName: "SPIR" , Opts); |
73 | } |
74 | |
75 | void SPIR32TargetInfo::getTargetDefines(const LangOptions &Opts, |
76 | MacroBuilder &Builder) const { |
77 | SPIRTargetInfo::getTargetDefines(Opts, Builder); |
78 | DefineStd(Builder, MacroName: "SPIR32" , Opts); |
79 | } |
80 | |
81 | void SPIR64TargetInfo::getTargetDefines(const LangOptions &Opts, |
82 | MacroBuilder &Builder) const { |
83 | SPIRTargetInfo::getTargetDefines(Opts, Builder); |
84 | DefineStd(Builder, MacroName: "SPIR64" , Opts); |
85 | } |
86 | |
87 | void BaseSPIRVTargetInfo::getTargetDefines(const LangOptions &Opts, |
88 | MacroBuilder &Builder) const { |
89 | DefineStd(Builder, MacroName: "SPIRV" , Opts); |
90 | if (Opts.HLSL) |
91 | DefineStd(Builder, MacroName: "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, MacroName: "SPIRV32" , Opts); |
103 | } |
104 | |
105 | void SPIRV64TargetInfo::getTargetDefines(const LangOptions &Opts, |
106 | MacroBuilder &Builder) const { |
107 | BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); |
108 | DefineStd(Builder, MacroName: "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(GPU: {}, T: getTriple(), Features); |
121 | |
122 | return TargetInfo::initFeatureMap(Features, Diags, CPU: {}, 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, MacroName: "SPIRV64" , Opts); |
144 | |
145 | Builder.defineMacro(Name: "__AMD__" ); |
146 | Builder.defineMacro(Name: "__AMDGPU__" ); |
147 | Builder.defineMacro(Name: "__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 | |