xref: /freebsd-src/contrib/llvm-project/clang/lib/Basic/Targets/SPIR.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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