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