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