xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceGlobalInits.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceGlobalInits.h - Global declarations -------*- C++ -*-===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                        The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares the representation of function declarations, global variable
12*03ce13f7SAndroid Build Coastguard Worker /// declarations, and the corresponding variable initializers in Subzero.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker /// Global variable initializers are represented as a sequence of simple
15*03ce13f7SAndroid Build Coastguard Worker /// initializers.
16*03ce13f7SAndroid Build Coastguard Worker ///
17*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
18*03ce13f7SAndroid Build Coastguard Worker 
19*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEGLOBALINITS_H
20*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEGLOBALINITS_H
21*03ce13f7SAndroid Build Coastguard Worker 
22*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceFixups.h"
24*03ce13f7SAndroid Build Coastguard Worker #include "IceGlobalContext.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "IceIntrinsics.h"
26*03ce13f7SAndroid Build Coastguard Worker #include "IceMangling.h"
27*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h"
28*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h"
29*03ce13f7SAndroid Build Coastguard Worker 
30*03ce13f7SAndroid Build Coastguard Worker #ifdef __clang__
31*03ce13f7SAndroid Build Coastguard Worker #pragma clang diagnostic push
32*03ce13f7SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wunused-parameter"
33*03ce13f7SAndroid Build Coastguard Worker #endif // __clang__
34*03ce13f7SAndroid Build Coastguard Worker 
35*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" // for NaClBitcodeRecord.
36*03ce13f7SAndroid Build Coastguard Worker #include "llvm/IR/CallingConv.h"
37*03ce13f7SAndroid Build Coastguard Worker #include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes.
38*03ce13f7SAndroid Build Coastguard Worker 
39*03ce13f7SAndroid Build Coastguard Worker #ifdef __clang__
40*03ce13f7SAndroid Build Coastguard Worker #pragma clang diagnostic pop
41*03ce13f7SAndroid Build Coastguard Worker #endif // __clang__
42*03ce13f7SAndroid Build Coastguard Worker 
43*03ce13f7SAndroid Build Coastguard Worker #include <memory>
44*03ce13f7SAndroid Build Coastguard Worker #include <utility>
45*03ce13f7SAndroid Build Coastguard Worker 
46*03ce13f7SAndroid Build Coastguard Worker // TODO(kschimpf): Remove ourselves from using LLVM representation for calling
47*03ce13f7SAndroid Build Coastguard Worker // conventions and linkage types.
48*03ce13f7SAndroid Build Coastguard Worker 
49*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
50*03ce13f7SAndroid Build Coastguard Worker 
51*03ce13f7SAndroid Build Coastguard Worker /// Base class for global variable and function declarations.
52*03ce13f7SAndroid Build Coastguard Worker class GlobalDeclaration {
53*03ce13f7SAndroid Build Coastguard Worker   GlobalDeclaration() = delete;
54*03ce13f7SAndroid Build Coastguard Worker   GlobalDeclaration(const GlobalDeclaration &) = delete;
55*03ce13f7SAndroid Build Coastguard Worker   GlobalDeclaration &operator=(const GlobalDeclaration &) = delete;
56*03ce13f7SAndroid Build Coastguard Worker 
57*03ce13f7SAndroid Build Coastguard Worker public:
58*03ce13f7SAndroid Build Coastguard Worker   /// Discriminator for LLVM-style RTTI.
59*03ce13f7SAndroid Build Coastguard Worker   enum GlobalDeclarationKind {
60*03ce13f7SAndroid Build Coastguard Worker     FunctionDeclarationKind,
61*03ce13f7SAndroid Build Coastguard Worker     VariableDeclarationKind
62*03ce13f7SAndroid Build Coastguard Worker   };
getKind()63*03ce13f7SAndroid Build Coastguard Worker   GlobalDeclarationKind getKind() const { return Kind; }
getName()64*03ce13f7SAndroid Build Coastguard Worker   GlobalString getName() const { return Name; }
setName(GlobalContext * Ctx,const std::string & NewName)65*03ce13f7SAndroid Build Coastguard Worker   void setName(GlobalContext *Ctx, const std::string &NewName) {
66*03ce13f7SAndroid Build Coastguard Worker     Name = Ctx->getGlobalString(getSuppressMangling() ? NewName
67*03ce13f7SAndroid Build Coastguard Worker                                                       : mangleName(NewName));
68*03ce13f7SAndroid Build Coastguard Worker   }
setName(GlobalString NewName)69*03ce13f7SAndroid Build Coastguard Worker   void setName(GlobalString NewName) { Name = NewName; }
setName(GlobalContext * Ctx)70*03ce13f7SAndroid Build Coastguard Worker   void setName(GlobalContext *Ctx) {
71*03ce13f7SAndroid Build Coastguard Worker     Name = GlobalString::createWithoutString(Ctx);
72*03ce13f7SAndroid Build Coastguard Worker   }
hasName()73*03ce13f7SAndroid Build Coastguard Worker   bool hasName() const { return Name.hasStdString(); }
isInternal()74*03ce13f7SAndroid Build Coastguard Worker   bool isInternal() const {
75*03ce13f7SAndroid Build Coastguard Worker     return Linkage == llvm::GlobalValue::InternalLinkage;
76*03ce13f7SAndroid Build Coastguard Worker   }
getLinkage()77*03ce13f7SAndroid Build Coastguard Worker   llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; }
setLinkage(llvm::GlobalValue::LinkageTypes L)78*03ce13f7SAndroid Build Coastguard Worker   void setLinkage(llvm::GlobalValue::LinkageTypes L) {
79*03ce13f7SAndroid Build Coastguard Worker     assert(!hasName());
80*03ce13f7SAndroid Build Coastguard Worker     Linkage = L;
81*03ce13f7SAndroid Build Coastguard Worker   }
isExternal()82*03ce13f7SAndroid Build Coastguard Worker   bool isExternal() const {
83*03ce13f7SAndroid Build Coastguard Worker     return Linkage == llvm::GlobalValue::ExternalLinkage;
84*03ce13f7SAndroid Build Coastguard Worker   }
85*03ce13f7SAndroid Build Coastguard Worker   virtual ~GlobalDeclaration() = default;
86*03ce13f7SAndroid Build Coastguard Worker 
87*03ce13f7SAndroid Build Coastguard Worker   /// Prints out type of the global declaration.
88*03ce13f7SAndroid Build Coastguard Worker   virtual void dumpType(Ostream &Stream) const = 0;
89*03ce13f7SAndroid Build Coastguard Worker 
90*03ce13f7SAndroid Build Coastguard Worker   /// Prints out the global declaration.
91*03ce13f7SAndroid Build Coastguard Worker   virtual void dump(Ostream &Stream) const = 0;
92*03ce13f7SAndroid Build Coastguard Worker 
93*03ce13f7SAndroid Build Coastguard Worker   /// Returns true if when emitting names, we should suppress mangling.
94*03ce13f7SAndroid Build Coastguard Worker   virtual bool getSuppressMangling() const = 0;
95*03ce13f7SAndroid Build Coastguard Worker 
96*03ce13f7SAndroid Build Coastguard Worker   /// Returns textual name of linkage.
getLinkageName()97*03ce13f7SAndroid Build Coastguard Worker   const char *getLinkageName() const {
98*03ce13f7SAndroid Build Coastguard Worker     return isInternal() ? "internal" : "external";
99*03ce13f7SAndroid Build Coastguard Worker   }
100*03ce13f7SAndroid Build Coastguard Worker 
101*03ce13f7SAndroid Build Coastguard Worker protected:
GlobalDeclaration(GlobalDeclarationKind Kind,llvm::GlobalValue::LinkageTypes Linkage)102*03ce13f7SAndroid Build Coastguard Worker   GlobalDeclaration(GlobalDeclarationKind Kind,
103*03ce13f7SAndroid Build Coastguard Worker                     llvm::GlobalValue::LinkageTypes Linkage)
104*03ce13f7SAndroid Build Coastguard Worker       : Kind(Kind), Linkage(Linkage) {}
105*03ce13f7SAndroid Build Coastguard Worker 
106*03ce13f7SAndroid Build Coastguard Worker   /// Returns true if linkage is defined correctly for the global declaration,
107*03ce13f7SAndroid Build Coastguard Worker   /// based on default rules.
verifyLinkageDefault()108*03ce13f7SAndroid Build Coastguard Worker   bool verifyLinkageDefault() const {
109*03ce13f7SAndroid Build Coastguard Worker     switch (Linkage) {
110*03ce13f7SAndroid Build Coastguard Worker     default:
111*03ce13f7SAndroid Build Coastguard Worker       return false;
112*03ce13f7SAndroid Build Coastguard Worker     case llvm::GlobalValue::InternalLinkage:
113*03ce13f7SAndroid Build Coastguard Worker       return true;
114*03ce13f7SAndroid Build Coastguard Worker     case llvm::GlobalValue::ExternalLinkage:
115*03ce13f7SAndroid Build Coastguard Worker       return getFlags().getAllowExternDefinedSymbols();
116*03ce13f7SAndroid Build Coastguard Worker     }
117*03ce13f7SAndroid Build Coastguard Worker   }
118*03ce13f7SAndroid Build Coastguard Worker 
119*03ce13f7SAndroid Build Coastguard Worker   const GlobalDeclarationKind Kind;
120*03ce13f7SAndroid Build Coastguard Worker   llvm::GlobalValue::LinkageTypes Linkage;
121*03ce13f7SAndroid Build Coastguard Worker   GlobalString Name;
122*03ce13f7SAndroid Build Coastguard Worker };
123*03ce13f7SAndroid Build Coastguard Worker 
124*03ce13f7SAndroid Build Coastguard Worker /// Models a function declaration. This includes the type signature of the
125*03ce13f7SAndroid Build Coastguard Worker /// function, its calling conventions, and its linkage.
126*03ce13f7SAndroid Build Coastguard Worker class FunctionDeclaration : public GlobalDeclaration {
127*03ce13f7SAndroid Build Coastguard Worker   FunctionDeclaration() = delete;
128*03ce13f7SAndroid Build Coastguard Worker   FunctionDeclaration(const FunctionDeclaration &) = delete;
129*03ce13f7SAndroid Build Coastguard Worker   FunctionDeclaration &operator=(const FunctionDeclaration &) = delete;
130*03ce13f7SAndroid Build Coastguard Worker 
131*03ce13f7SAndroid Build Coastguard Worker public:
create(GlobalContext * Context,const FuncSigType & Signature,llvm::CallingConv::ID CallingConv,llvm::GlobalValue::LinkageTypes Linkage,bool IsProto)132*03ce13f7SAndroid Build Coastguard Worker   static FunctionDeclaration *create(GlobalContext *Context,
133*03ce13f7SAndroid Build Coastguard Worker                                      const FuncSigType &Signature,
134*03ce13f7SAndroid Build Coastguard Worker                                      llvm::CallingConv::ID CallingConv,
135*03ce13f7SAndroid Build Coastguard Worker                                      llvm::GlobalValue::LinkageTypes Linkage,
136*03ce13f7SAndroid Build Coastguard Worker                                      bool IsProto) {
137*03ce13f7SAndroid Build Coastguard Worker     return new (Context->allocate<FunctionDeclaration>())
138*03ce13f7SAndroid Build Coastguard Worker         FunctionDeclaration(Signature, CallingConv, Linkage, IsProto);
139*03ce13f7SAndroid Build Coastguard Worker   }
getSignature()140*03ce13f7SAndroid Build Coastguard Worker   const FuncSigType &getSignature() const { return Signature; }
getCallingConv()141*03ce13f7SAndroid Build Coastguard Worker   llvm::CallingConv::ID getCallingConv() const { return CallingConv; }
142*03ce13f7SAndroid Build Coastguard Worker   /// isProto implies that there isn't a (local) definition for the function.
isProto()143*03ce13f7SAndroid Build Coastguard Worker   bool isProto() const { return IsProto; }
classof(const GlobalDeclaration * Addr)144*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const GlobalDeclaration *Addr) {
145*03ce13f7SAndroid Build Coastguard Worker     return Addr->getKind() == FunctionDeclarationKind;
146*03ce13f7SAndroid Build Coastguard Worker   }
147*03ce13f7SAndroid Build Coastguard Worker   void dumpType(Ostream &Stream) const final;
148*03ce13f7SAndroid Build Coastguard Worker   void dump(Ostream &Stream) const final;
getSuppressMangling()149*03ce13f7SAndroid Build Coastguard Worker   bool getSuppressMangling() const final { return isExternal() && IsProto; }
150*03ce13f7SAndroid Build Coastguard Worker 
151*03ce13f7SAndroid Build Coastguard Worker   /// Returns true if linkage is correct for the function declaration.
verifyLinkageCorrect(const GlobalContext * Ctx)152*03ce13f7SAndroid Build Coastguard Worker   bool verifyLinkageCorrect(const GlobalContext *Ctx) const {
153*03ce13f7SAndroid Build Coastguard Worker     return verifyLinkageDefault();
154*03ce13f7SAndroid Build Coastguard Worker   }
155*03ce13f7SAndroid Build Coastguard Worker 
156*03ce13f7SAndroid Build Coastguard Worker   /// Validates that the type signature of the function is correct. Returns true
157*03ce13f7SAndroid Build Coastguard Worker   /// if valid.
158*03ce13f7SAndroid Build Coastguard Worker   bool validateTypeSignature() const;
159*03ce13f7SAndroid Build Coastguard Worker 
160*03ce13f7SAndroid Build Coastguard Worker   /// Generates an error message describing why validateTypeSignature returns
161*03ce13f7SAndroid Build Coastguard Worker   /// false.
162*03ce13f7SAndroid Build Coastguard Worker   std::string getTypeSignatureError(const GlobalContext *Ctx);
163*03ce13f7SAndroid Build Coastguard Worker 
164*03ce13f7SAndroid Build Coastguard Worker private:
165*03ce13f7SAndroid Build Coastguard Worker   const Ice::FuncSigType Signature;
166*03ce13f7SAndroid Build Coastguard Worker   llvm::CallingConv::ID CallingConv;
167*03ce13f7SAndroid Build Coastguard Worker   const bool IsProto;
168*03ce13f7SAndroid Build Coastguard Worker 
FunctionDeclaration(const FuncSigType & Signature,llvm::CallingConv::ID CallingConv,llvm::GlobalValue::LinkageTypes Linkage,bool IsProto)169*03ce13f7SAndroid Build Coastguard Worker   FunctionDeclaration(const FuncSigType &Signature,
170*03ce13f7SAndroid Build Coastguard Worker                       llvm::CallingConv::ID CallingConv,
171*03ce13f7SAndroid Build Coastguard Worker                       llvm::GlobalValue::LinkageTypes Linkage, bool IsProto)
172*03ce13f7SAndroid Build Coastguard Worker       : GlobalDeclaration(FunctionDeclarationKind, Linkage),
173*03ce13f7SAndroid Build Coastguard Worker         Signature(Signature), CallingConv(CallingConv), IsProto(IsProto) {}
174*03ce13f7SAndroid Build Coastguard Worker };
175*03ce13f7SAndroid Build Coastguard Worker 
176*03ce13f7SAndroid Build Coastguard Worker /// Models a global variable declaration, and its initializers.
177*03ce13f7SAndroid Build Coastguard Worker class VariableDeclaration : public GlobalDeclaration {
178*03ce13f7SAndroid Build Coastguard Worker   VariableDeclaration(const VariableDeclaration &) = delete;
179*03ce13f7SAndroid Build Coastguard Worker   VariableDeclaration &operator=(const VariableDeclaration &) = delete;
180*03ce13f7SAndroid Build Coastguard Worker 
181*03ce13f7SAndroid Build Coastguard Worker public:
182*03ce13f7SAndroid Build Coastguard Worker   /// Base class for a global variable initializer.
183*03ce13f7SAndroid Build Coastguard Worker   class Initializer {
184*03ce13f7SAndroid Build Coastguard Worker     Initializer(const Initializer &) = delete;
185*03ce13f7SAndroid Build Coastguard Worker     Initializer &operator=(const Initializer &) = delete;
186*03ce13f7SAndroid Build Coastguard Worker 
187*03ce13f7SAndroid Build Coastguard Worker   public:
188*03ce13f7SAndroid Build Coastguard Worker     /// Discriminator for LLVM-style RTTI.
189*03ce13f7SAndroid Build Coastguard Worker     enum InitializerKind {
190*03ce13f7SAndroid Build Coastguard Worker       DataInitializerKind,
191*03ce13f7SAndroid Build Coastguard Worker       ZeroInitializerKind,
192*03ce13f7SAndroid Build Coastguard Worker       RelocInitializerKind
193*03ce13f7SAndroid Build Coastguard Worker     };
getKind()194*03ce13f7SAndroid Build Coastguard Worker     InitializerKind getKind() const { return Kind; }
195*03ce13f7SAndroid Build Coastguard Worker     virtual SizeT getNumBytes() const = 0;
196*03ce13f7SAndroid Build Coastguard Worker     virtual void dump(Ostream &Stream) const = 0;
197*03ce13f7SAndroid Build Coastguard Worker     virtual void dumpType(Ostream &Stream) const;
198*03ce13f7SAndroid Build Coastguard Worker 
199*03ce13f7SAndroid Build Coastguard Worker   protected:
Initializer(InitializerKind Kind)200*03ce13f7SAndroid Build Coastguard Worker     explicit Initializer(InitializerKind Kind) : Kind(Kind) {}
201*03ce13f7SAndroid Build Coastguard Worker 
202*03ce13f7SAndroid Build Coastguard Worker   private:
203*03ce13f7SAndroid Build Coastguard Worker     const InitializerKind Kind;
204*03ce13f7SAndroid Build Coastguard Worker   };
205*03ce13f7SAndroid Build Coastguard Worker   static_assert(std::is_trivially_destructible<Initializer>::value,
206*03ce13f7SAndroid Build Coastguard Worker                 "Initializer must be trivially destructible.");
207*03ce13f7SAndroid Build Coastguard Worker 
208*03ce13f7SAndroid Build Coastguard Worker   /// Models the data in a data initializer.
209*03ce13f7SAndroid Build Coastguard Worker   using DataVecType = char *;
210*03ce13f7SAndroid Build Coastguard Worker 
211*03ce13f7SAndroid Build Coastguard Worker   /// Defines a sequence of byte values as a data initializer.
212*03ce13f7SAndroid Build Coastguard Worker   class DataInitializer : public Initializer {
213*03ce13f7SAndroid Build Coastguard Worker     DataInitializer(const DataInitializer &) = delete;
214*03ce13f7SAndroid Build Coastguard Worker     DataInitializer &operator=(const DataInitializer &) = delete;
215*03ce13f7SAndroid Build Coastguard Worker 
216*03ce13f7SAndroid Build Coastguard Worker   public:
217*03ce13f7SAndroid Build Coastguard Worker     template <class... Args>
create(VariableDeclarationList * VDL,Args &&...TheArgs)218*03ce13f7SAndroid Build Coastguard Worker     static DataInitializer *create(VariableDeclarationList *VDL,
219*03ce13f7SAndroid Build Coastguard Worker                                    Args &&... TheArgs) {
220*03ce13f7SAndroid Build Coastguard Worker       return new (VDL->allocate_initializer<DataInitializer>())
221*03ce13f7SAndroid Build Coastguard Worker           DataInitializer(VDL, std::forward<Args>(TheArgs)...);
222*03ce13f7SAndroid Build Coastguard Worker     }
223*03ce13f7SAndroid Build Coastguard Worker 
getContents()224*03ce13f7SAndroid Build Coastguard Worker     const llvm::StringRef getContents() const {
225*03ce13f7SAndroid Build Coastguard Worker       return llvm::StringRef(Contents, ContentsSize);
226*03ce13f7SAndroid Build Coastguard Worker     }
getNumBytes()227*03ce13f7SAndroid Build Coastguard Worker     SizeT getNumBytes() const final { return ContentsSize; }
228*03ce13f7SAndroid Build Coastguard Worker     void dump(Ostream &Stream) const final;
classof(const Initializer * D)229*03ce13f7SAndroid Build Coastguard Worker     static bool classof(const Initializer *D) {
230*03ce13f7SAndroid Build Coastguard Worker       return D->getKind() == DataInitializerKind;
231*03ce13f7SAndroid Build Coastguard Worker     }
232*03ce13f7SAndroid Build Coastguard Worker 
233*03ce13f7SAndroid Build Coastguard Worker   private:
DataInitializer(VariableDeclarationList * VDL,const llvm::NaClBitcodeRecord::RecordVector & Values)234*03ce13f7SAndroid Build Coastguard Worker     DataInitializer(VariableDeclarationList *VDL,
235*03ce13f7SAndroid Build Coastguard Worker                     const llvm::NaClBitcodeRecord::RecordVector &Values)
236*03ce13f7SAndroid Build Coastguard Worker         : Initializer(DataInitializerKind), ContentsSize(Values.size()),
237*03ce13f7SAndroid Build Coastguard Worker           // ugh, we should actually do new char[], but this may involve
238*03ce13f7SAndroid Build Coastguard Worker           // implementation-specific details. Given that Contents is arena
239*03ce13f7SAndroid Build Coastguard Worker           // allocated, and never delete[]d, just use char --
240*03ce13f7SAndroid Build Coastguard Worker           // AllocOwner->allocate_array will allocate a buffer with the right
241*03ce13f7SAndroid Build Coastguard Worker           // size.
242*03ce13f7SAndroid Build Coastguard Worker           Contents(new (VDL->allocate_initializer<char>(ContentsSize)) char) {
243*03ce13f7SAndroid Build Coastguard Worker       for (SizeT I = 0; I < Values.size(); ++I)
244*03ce13f7SAndroid Build Coastguard Worker         Contents[I] = static_cast<int8_t>(Values[I]);
245*03ce13f7SAndroid Build Coastguard Worker     }
246*03ce13f7SAndroid Build Coastguard Worker 
DataInitializer(VariableDeclarationList * VDL,const char * Str,size_t StrLen)247*03ce13f7SAndroid Build Coastguard Worker     DataInitializer(VariableDeclarationList *VDL, const char *Str,
248*03ce13f7SAndroid Build Coastguard Worker                     size_t StrLen)
249*03ce13f7SAndroid Build Coastguard Worker         : Initializer(DataInitializerKind), ContentsSize(StrLen),
250*03ce13f7SAndroid Build Coastguard Worker           Contents(new (VDL->allocate_initializer<char>(ContentsSize)) char) {
251*03ce13f7SAndroid Build Coastguard Worker       for (size_t i = 0; i < StrLen; ++i)
252*03ce13f7SAndroid Build Coastguard Worker         Contents[i] = Str[i];
253*03ce13f7SAndroid Build Coastguard Worker     }
254*03ce13f7SAndroid Build Coastguard Worker 
255*03ce13f7SAndroid Build Coastguard Worker     /// The byte contents of the data initializer.
256*03ce13f7SAndroid Build Coastguard Worker     const SizeT ContentsSize;
257*03ce13f7SAndroid Build Coastguard Worker     DataVecType Contents;
258*03ce13f7SAndroid Build Coastguard Worker   };
259*03ce13f7SAndroid Build Coastguard Worker   static_assert(std::is_trivially_destructible<DataInitializer>::value,
260*03ce13f7SAndroid Build Coastguard Worker                 "DataInitializer must be trivially destructible.");
261*03ce13f7SAndroid Build Coastguard Worker 
262*03ce13f7SAndroid Build Coastguard Worker   /// Defines a sequence of bytes initialized to zero.
263*03ce13f7SAndroid Build Coastguard Worker   class ZeroInitializer : public Initializer {
264*03ce13f7SAndroid Build Coastguard Worker     ZeroInitializer(const ZeroInitializer &) = delete;
265*03ce13f7SAndroid Build Coastguard Worker     ZeroInitializer &operator=(const ZeroInitializer &) = delete;
266*03ce13f7SAndroid Build Coastguard Worker 
267*03ce13f7SAndroid Build Coastguard Worker   public:
create(VariableDeclarationList * VDL,SizeT Size)268*03ce13f7SAndroid Build Coastguard Worker     static ZeroInitializer *create(VariableDeclarationList *VDL, SizeT Size) {
269*03ce13f7SAndroid Build Coastguard Worker       return new (VDL->allocate_initializer<ZeroInitializer>())
270*03ce13f7SAndroid Build Coastguard Worker           ZeroInitializer(Size);
271*03ce13f7SAndroid Build Coastguard Worker     }
getNumBytes()272*03ce13f7SAndroid Build Coastguard Worker     SizeT getNumBytes() const final { return Size; }
273*03ce13f7SAndroid Build Coastguard Worker     void dump(Ostream &Stream) const final;
classof(const Initializer * Z)274*03ce13f7SAndroid Build Coastguard Worker     static bool classof(const Initializer *Z) {
275*03ce13f7SAndroid Build Coastguard Worker       return Z->getKind() == ZeroInitializerKind;
276*03ce13f7SAndroid Build Coastguard Worker     }
277*03ce13f7SAndroid Build Coastguard Worker 
278*03ce13f7SAndroid Build Coastguard Worker   private:
ZeroInitializer(SizeT Size)279*03ce13f7SAndroid Build Coastguard Worker     explicit ZeroInitializer(SizeT Size)
280*03ce13f7SAndroid Build Coastguard Worker         : Initializer(ZeroInitializerKind), Size(Size) {}
281*03ce13f7SAndroid Build Coastguard Worker 
282*03ce13f7SAndroid Build Coastguard Worker     /// The number of bytes to be zero initialized.
283*03ce13f7SAndroid Build Coastguard Worker     SizeT Size;
284*03ce13f7SAndroid Build Coastguard Worker   };
285*03ce13f7SAndroid Build Coastguard Worker   static_assert(std::is_trivially_destructible<ZeroInitializer>::value,
286*03ce13f7SAndroid Build Coastguard Worker                 "ZeroInitializer must be trivially destructible.");
287*03ce13f7SAndroid Build Coastguard Worker 
288*03ce13f7SAndroid Build Coastguard Worker   /// Defines the relocation value of another global declaration.
289*03ce13f7SAndroid Build Coastguard Worker   class RelocInitializer : public Initializer {
290*03ce13f7SAndroid Build Coastguard Worker     RelocInitializer(const RelocInitializer &) = delete;
291*03ce13f7SAndroid Build Coastguard Worker     RelocInitializer &operator=(const RelocInitializer &) = delete;
292*03ce13f7SAndroid Build Coastguard Worker 
293*03ce13f7SAndroid Build Coastguard Worker   public:
create(VariableDeclarationList * VDL,const GlobalDeclaration * Declaration,const RelocOffsetArray & OffsetExpr)294*03ce13f7SAndroid Build Coastguard Worker     static RelocInitializer *create(VariableDeclarationList *VDL,
295*03ce13f7SAndroid Build Coastguard Worker                                     const GlobalDeclaration *Declaration,
296*03ce13f7SAndroid Build Coastguard Worker                                     const RelocOffsetArray &OffsetExpr) {
297*03ce13f7SAndroid Build Coastguard Worker       constexpr bool NoFixup = false;
298*03ce13f7SAndroid Build Coastguard Worker       return new (VDL->allocate_initializer<RelocInitializer>())
299*03ce13f7SAndroid Build Coastguard Worker           RelocInitializer(VDL, Declaration, OffsetExpr, NoFixup);
300*03ce13f7SAndroid Build Coastguard Worker     }
301*03ce13f7SAndroid Build Coastguard Worker 
create(VariableDeclarationList * VDL,const GlobalDeclaration * Declaration,const RelocOffsetArray & OffsetExpr,FixupKind Fixup)302*03ce13f7SAndroid Build Coastguard Worker     static RelocInitializer *create(VariableDeclarationList *VDL,
303*03ce13f7SAndroid Build Coastguard Worker                                     const GlobalDeclaration *Declaration,
304*03ce13f7SAndroid Build Coastguard Worker                                     const RelocOffsetArray &OffsetExpr,
305*03ce13f7SAndroid Build Coastguard Worker                                     FixupKind Fixup) {
306*03ce13f7SAndroid Build Coastguard Worker       constexpr bool HasFixup = true;
307*03ce13f7SAndroid Build Coastguard Worker       return new (VDL->allocate_initializer<RelocInitializer>())
308*03ce13f7SAndroid Build Coastguard Worker           RelocInitializer(VDL, Declaration, OffsetExpr, HasFixup, Fixup);
309*03ce13f7SAndroid Build Coastguard Worker     }
310*03ce13f7SAndroid Build Coastguard Worker 
getOffset()311*03ce13f7SAndroid Build Coastguard Worker     RelocOffsetT getOffset() const {
312*03ce13f7SAndroid Build Coastguard Worker       RelocOffsetT Offset = 0;
313*03ce13f7SAndroid Build Coastguard Worker       for (SizeT i = 0; i < OffsetExprSize; ++i) {
314*03ce13f7SAndroid Build Coastguard Worker         Offset += OffsetExpr[i]->getOffset();
315*03ce13f7SAndroid Build Coastguard Worker       }
316*03ce13f7SAndroid Build Coastguard Worker       return Offset;
317*03ce13f7SAndroid Build Coastguard Worker     }
318*03ce13f7SAndroid Build Coastguard Worker 
hasFixup()319*03ce13f7SAndroid Build Coastguard Worker     bool hasFixup() const { return HasFixup; }
getFixup()320*03ce13f7SAndroid Build Coastguard Worker     FixupKind getFixup() const {
321*03ce13f7SAndroid Build Coastguard Worker       assert(HasFixup);
322*03ce13f7SAndroid Build Coastguard Worker       return Fixup;
323*03ce13f7SAndroid Build Coastguard Worker     }
324*03ce13f7SAndroid Build Coastguard Worker 
getDeclaration()325*03ce13f7SAndroid Build Coastguard Worker     const GlobalDeclaration *getDeclaration() const { return Declaration; }
getNumBytes()326*03ce13f7SAndroid Build Coastguard Worker     SizeT getNumBytes() const final { return RelocAddrSize; }
327*03ce13f7SAndroid Build Coastguard Worker     void dump(Ostream &Stream) const final;
328*03ce13f7SAndroid Build Coastguard Worker     void dumpType(Ostream &Stream) const final;
classof(const Initializer * R)329*03ce13f7SAndroid Build Coastguard Worker     static bool classof(const Initializer *R) {
330*03ce13f7SAndroid Build Coastguard Worker       return R->getKind() == RelocInitializerKind;
331*03ce13f7SAndroid Build Coastguard Worker     }
332*03ce13f7SAndroid Build Coastguard Worker 
333*03ce13f7SAndroid Build Coastguard Worker   private:
334*03ce13f7SAndroid Build Coastguard Worker     RelocInitializer(VariableDeclarationList *VDL,
335*03ce13f7SAndroid Build Coastguard Worker                      const GlobalDeclaration *Declaration,
336*03ce13f7SAndroid Build Coastguard Worker                      const RelocOffsetArray &OffsetExpr, bool HasFixup,
337*03ce13f7SAndroid Build Coastguard Worker                      FixupKind Fixup = 0)
Initializer(RelocInitializerKind)338*03ce13f7SAndroid Build Coastguard Worker         : Initializer(RelocInitializerKind),
339*03ce13f7SAndroid Build Coastguard Worker           Declaration(Declaration), // The global declaration used in the reloc.
340*03ce13f7SAndroid Build Coastguard Worker           OffsetExprSize(OffsetExpr.size()),
341*03ce13f7SAndroid Build Coastguard Worker           OffsetExpr(new (VDL->allocate_initializer<RelocOffset *>(
342*03ce13f7SAndroid Build Coastguard Worker               OffsetExprSize)) RelocOffset *),
343*03ce13f7SAndroid Build Coastguard Worker           HasFixup(HasFixup), Fixup(Fixup) {
344*03ce13f7SAndroid Build Coastguard Worker       for (SizeT i = 0; i < OffsetExprSize; ++i) {
345*03ce13f7SAndroid Build Coastguard Worker         this->OffsetExpr[i] = OffsetExpr[i];
346*03ce13f7SAndroid Build Coastguard Worker       }
347*03ce13f7SAndroid Build Coastguard Worker     }
348*03ce13f7SAndroid Build Coastguard Worker 
349*03ce13f7SAndroid Build Coastguard Worker     const GlobalDeclaration *Declaration;
350*03ce13f7SAndroid Build Coastguard Worker     /// The offset to add to the relocation.
351*03ce13f7SAndroid Build Coastguard Worker     const SizeT OffsetExprSize;
352*03ce13f7SAndroid Build Coastguard Worker     RelocOffset **OffsetExpr;
353*03ce13f7SAndroid Build Coastguard Worker     const bool HasFixup = false;
354*03ce13f7SAndroid Build Coastguard Worker     const FixupKind Fixup = 0;
355*03ce13f7SAndroid Build Coastguard Worker   };
356*03ce13f7SAndroid Build Coastguard Worker   static_assert(std::is_trivially_destructible<RelocInitializer>::value,
357*03ce13f7SAndroid Build Coastguard Worker                 "RelocInitializer must be trivially destructible.");
358*03ce13f7SAndroid Build Coastguard Worker 
359*03ce13f7SAndroid Build Coastguard Worker   /// Models the list of initializers.
360*03ce13f7SAndroid Build Coastguard Worker   // TODO(jpp): missing allocator.
361*03ce13f7SAndroid Build Coastguard Worker   using InitializerListType = std::vector<Initializer *>;
362*03ce13f7SAndroid Build Coastguard Worker 
363*03ce13f7SAndroid Build Coastguard Worker   static VariableDeclaration *create(VariableDeclarationList *VDL,
364*03ce13f7SAndroid Build Coastguard Worker                                      bool SuppressMangling = false,
365*03ce13f7SAndroid Build Coastguard Worker                                      llvm::GlobalValue::LinkageTypes Linkage =
366*03ce13f7SAndroid Build Coastguard Worker                                          llvm::GlobalValue::InternalLinkage) {
367*03ce13f7SAndroid Build Coastguard Worker     return new (VDL->allocate_variable_declaration<VariableDeclaration>())
368*03ce13f7SAndroid Build Coastguard Worker         VariableDeclaration(Linkage, SuppressMangling);
369*03ce13f7SAndroid Build Coastguard Worker   }
370*03ce13f7SAndroid Build Coastguard Worker 
createExternal(VariableDeclarationList * VDL)371*03ce13f7SAndroid Build Coastguard Worker   static VariableDeclaration *createExternal(VariableDeclarationList *VDL) {
372*03ce13f7SAndroid Build Coastguard Worker     constexpr bool SuppressMangling = true;
373*03ce13f7SAndroid Build Coastguard Worker     constexpr llvm::GlobalValue::LinkageTypes Linkage =
374*03ce13f7SAndroid Build Coastguard Worker         llvm::GlobalValue::ExternalLinkage;
375*03ce13f7SAndroid Build Coastguard Worker     return create(VDL, SuppressMangling, Linkage);
376*03ce13f7SAndroid Build Coastguard Worker   }
377*03ce13f7SAndroid Build Coastguard Worker 
getInitializers()378*03ce13f7SAndroid Build Coastguard Worker   const InitializerListType &getInitializers() const { return Initializers; }
getIsConstant()379*03ce13f7SAndroid Build Coastguard Worker   bool getIsConstant() const { return IsConstant; }
setIsConstant(bool NewValue)380*03ce13f7SAndroid Build Coastguard Worker   void setIsConstant(bool NewValue) { IsConstant = NewValue; }
getAlignment()381*03ce13f7SAndroid Build Coastguard Worker   uint32_t getAlignment() const { return Alignment; }
setAlignment(uint32_t NewAlignment)382*03ce13f7SAndroid Build Coastguard Worker   void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; }
hasInitializer()383*03ce13f7SAndroid Build Coastguard Worker   bool hasInitializer() const { return HasInitializer; }
hasNonzeroInitializer()384*03ce13f7SAndroid Build Coastguard Worker   bool hasNonzeroInitializer() const {
385*03ce13f7SAndroid Build Coastguard Worker     return !(Initializers.size() == 1 &&
386*03ce13f7SAndroid Build Coastguard Worker              llvm::isa<ZeroInitializer>(Initializers[0]));
387*03ce13f7SAndroid Build Coastguard Worker   }
388*03ce13f7SAndroid Build Coastguard Worker 
389*03ce13f7SAndroid Build Coastguard Worker   /// Returns the number of bytes for the initializer of the global address.
getNumBytes()390*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumBytes() const {
391*03ce13f7SAndroid Build Coastguard Worker     SizeT Count = 0;
392*03ce13f7SAndroid Build Coastguard Worker     for (const auto *Init : Initializers) {
393*03ce13f7SAndroid Build Coastguard Worker       Count += Init->getNumBytes();
394*03ce13f7SAndroid Build Coastguard Worker     }
395*03ce13f7SAndroid Build Coastguard Worker     return Count;
396*03ce13f7SAndroid Build Coastguard Worker   }
397*03ce13f7SAndroid Build Coastguard Worker 
398*03ce13f7SAndroid Build Coastguard Worker   /// Adds Initializer to the list of initializers. Takes ownership of the
399*03ce13f7SAndroid Build Coastguard Worker   /// initializer.
addInitializer(Initializer * Initializer)400*03ce13f7SAndroid Build Coastguard Worker   void addInitializer(Initializer *Initializer) {
401*03ce13f7SAndroid Build Coastguard Worker     const bool OldSuppressMangling = getSuppressMangling();
402*03ce13f7SAndroid Build Coastguard Worker     Initializers.emplace_back(Initializer);
403*03ce13f7SAndroid Build Coastguard Worker     HasInitializer = true;
404*03ce13f7SAndroid Build Coastguard Worker     // The getSuppressMangling() logic depends on whether the global variable
405*03ce13f7SAndroid Build Coastguard Worker     // has initializers.  If its value changed as a result of adding an
406*03ce13f7SAndroid Build Coastguard Worker     // initializer, then make sure we haven't previously set the name based on
407*03ce13f7SAndroid Build Coastguard Worker     // faulty SuppressMangling logic.
408*03ce13f7SAndroid Build Coastguard Worker     const bool SameMangling = (OldSuppressMangling == getSuppressMangling());
409*03ce13f7SAndroid Build Coastguard Worker     (void)SameMangling;
410*03ce13f7SAndroid Build Coastguard Worker     assert(Name.hasStdString() || SameMangling);
411*03ce13f7SAndroid Build Coastguard Worker   }
412*03ce13f7SAndroid Build Coastguard Worker 
413*03ce13f7SAndroid Build Coastguard Worker   /// Prints out type for initializer associated with the declaration to Stream.
414*03ce13f7SAndroid Build Coastguard Worker   void dumpType(Ostream &Stream) const final;
415*03ce13f7SAndroid Build Coastguard Worker 
416*03ce13f7SAndroid Build Coastguard Worker   /// Prints out the definition of the global variable declaration (including
417*03ce13f7SAndroid Build Coastguard Worker   /// initialization).
418*03ce13f7SAndroid Build Coastguard Worker   virtual void dump(Ostream &Stream) const override;
419*03ce13f7SAndroid Build Coastguard Worker 
420*03ce13f7SAndroid Build Coastguard Worker   /// Returns true if linkage is correct for the variable declaration.
verifyLinkageCorrect()421*03ce13f7SAndroid Build Coastguard Worker   bool verifyLinkageCorrect() const { return verifyLinkageDefault(); }
422*03ce13f7SAndroid Build Coastguard Worker 
classof(const GlobalDeclaration * Addr)423*03ce13f7SAndroid Build Coastguard Worker   static bool classof(const GlobalDeclaration *Addr) {
424*03ce13f7SAndroid Build Coastguard Worker     return Addr->getKind() == VariableDeclarationKind;
425*03ce13f7SAndroid Build Coastguard Worker   }
426*03ce13f7SAndroid Build Coastguard Worker 
getSuppressMangling()427*03ce13f7SAndroid Build Coastguard Worker   bool getSuppressMangling() const final {
428*03ce13f7SAndroid Build Coastguard Worker     if (ForceSuppressMangling)
429*03ce13f7SAndroid Build Coastguard Worker       return true;
430*03ce13f7SAndroid Build Coastguard Worker     return isExternal() && !hasInitializer();
431*03ce13f7SAndroid Build Coastguard Worker   }
432*03ce13f7SAndroid Build Coastguard Worker 
discardInitializers()433*03ce13f7SAndroid Build Coastguard Worker   void discardInitializers() { Initializers.clear(); }
434*03ce13f7SAndroid Build Coastguard Worker 
435*03ce13f7SAndroid Build Coastguard Worker private:
436*03ce13f7SAndroid Build Coastguard Worker   /// List of initializers for the declared variable.
437*03ce13f7SAndroid Build Coastguard Worker   InitializerListType Initializers;
438*03ce13f7SAndroid Build Coastguard Worker   bool HasInitializer = false;
439*03ce13f7SAndroid Build Coastguard Worker   /// The alignment of the declared variable.
440*03ce13f7SAndroid Build Coastguard Worker   uint32_t Alignment = 0;
441*03ce13f7SAndroid Build Coastguard Worker   /// True if a declared (global) constant.
442*03ce13f7SAndroid Build Coastguard Worker   bool IsConstant = false;
443*03ce13f7SAndroid Build Coastguard Worker   /// If set to true, force getSuppressMangling() to return true.
444*03ce13f7SAndroid Build Coastguard Worker   const bool ForceSuppressMangling;
445*03ce13f7SAndroid Build Coastguard Worker 
VariableDeclaration(llvm::GlobalValue::LinkageTypes Linkage,bool SuppressMangling)446*03ce13f7SAndroid Build Coastguard Worker   VariableDeclaration(llvm::GlobalValue::LinkageTypes Linkage,
447*03ce13f7SAndroid Build Coastguard Worker                       bool SuppressMangling)
448*03ce13f7SAndroid Build Coastguard Worker       : GlobalDeclaration(VariableDeclarationKind, Linkage),
449*03ce13f7SAndroid Build Coastguard Worker         ForceSuppressMangling(SuppressMangling) {}
450*03ce13f7SAndroid Build Coastguard Worker };
451*03ce13f7SAndroid Build Coastguard Worker 
452*03ce13f7SAndroid Build Coastguard Worker template <class StreamType>
453*03ce13f7SAndroid Build Coastguard Worker inline StreamType &operator<<(StreamType &Stream,
454*03ce13f7SAndroid Build Coastguard Worker                               const VariableDeclaration::Initializer &Init) {
455*03ce13f7SAndroid Build Coastguard Worker   Init.dump(Stream);
456*03ce13f7SAndroid Build Coastguard Worker   return Stream;
457*03ce13f7SAndroid Build Coastguard Worker }
458*03ce13f7SAndroid Build Coastguard Worker 
459*03ce13f7SAndroid Build Coastguard Worker template <class StreamType>
460*03ce13f7SAndroid Build Coastguard Worker inline StreamType &operator<<(StreamType &Stream,
461*03ce13f7SAndroid Build Coastguard Worker                               const GlobalDeclaration &Addr) {
462*03ce13f7SAndroid Build Coastguard Worker   Addr.dump(Stream);
463*03ce13f7SAndroid Build Coastguard Worker   return Stream;
464*03ce13f7SAndroid Build Coastguard Worker }
465*03ce13f7SAndroid Build Coastguard Worker 
466*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
467*03ce13f7SAndroid Build Coastguard Worker 
468*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEGLOBALINITS_H
469