Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceGlobalInits.h - Global initializers -------*- C++ -*-===// | 1 //===- subzero/src/IceGlobalInits.h - Global declarations -------*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file declares the representation of global addresses and | 10 // This file declares the representation of function declarations, |
| 11 // initializers in Subzero. Global initializers are represented as a | 11 // global variable declarations, and the corresponding variable |
| 12 // sequence of simple initializers. | 12 // initializers in Subzero. Global variable initializers are |
| 13 // represented as a sequence of simple initializers. | |
| 13 // | 14 // |
| 14 //===----------------------------------------------------------------------===// | 15 //===----------------------------------------------------------------------===// |
| 15 | 16 |
| 16 #ifndef SUBZERO_SRC_ICEGLOBALINITS_H | 17 #ifndef SUBZERO_SRC_ICEGLOBALINITS_H |
| 17 #define SUBZERO_SRC_ICEGLOBALINITS_H | 18 #define SUBZERO_SRC_ICEGLOBALINITS_H |
| 18 | 19 |
| 19 #include "IceDefs.h" | 20 #include "IceDefs.h" |
| 21 #include "IceTypes.h" | |
| 20 | 22 |
| 21 namespace llvm { | 23 #include "llvm/IR/CallingConv.h" |
|
Jim Stichnoth
2014/10/13 19:14:22
put these includes first
Karl
2014/10/13 20:48:03
Done.
| |
| 22 // TODO(kschimpf): Remove this dependency on LLVM IR. | 24 #include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes |
| 23 class Value; | 25 |
| 24 } | 26 // TODO(kschimpf): Remove ourselves from using LLVM representation for calling |
| 27 // conventions and linkage types. | |
| 25 | 28 |
| 26 namespace Ice { | 29 namespace Ice { |
| 27 | 30 |
| 28 /// Models a global address, and its initializers. | 31 /// Base class for global variable and function declarations. |
| 29 class GlobalAddress { | 32 class GlobalDeclaration { |
| 30 GlobalAddress(const GlobalAddress &) = delete; | 33 GlobalDeclaration(const GlobalDeclaration &) = delete; |
| 31 GlobalAddress &operator=(const GlobalAddress &) = delete; | 34 GlobalDeclaration &operator=(const GlobalDeclaration &) = delete; |
| 32 | 35 |
| 33 public: | 36 public: |
| 37 /// Discriminator for LLVM-style RTTI. | |
| 38 enum GlobalDeclarationKind { | |
| 39 FunctionDeclarationKind, | |
| 40 VariableDeclarationKind | |
| 41 }; | |
| 42 GlobalDeclarationKind getKind() const { return Kind; } | |
| 43 const IceString &getName() const { return Name; } | |
| 44 void setName(const IceString &NewName) { Name = NewName; } | |
| 45 bool hasName() const { return !Name.empty(); } | |
| 46 virtual ~GlobalDeclaration() {} | |
| 47 | |
| 48 /// Returns true if the declaration is external. | |
| 49 virtual bool getIsExternal() const = 0; | |
| 50 | |
| 51 /// Returns true if initialized (or defined if function declaration). | |
| 52 // virtual bool hasInitializer() const = 0; | |
|
Jim Stichnoth
2014/10/13 19:14:22
Not sure why this method is commented out here and
Karl
2014/10/13 20:48:03
Initialization (as pointed out by Jan) is a Variab
| |
| 53 | |
| 54 /// Prints out type of the global declaration. | |
| 55 virtual void dumpType(Ostream &Stream) const = 0; | |
| 56 | |
| 57 /// Prints out the global declaration. | |
| 58 virtual void dump(Ostream &Stream) const = 0; | |
| 59 | |
| 60 // Mangles name for cross tests, unless external and not defined locally | |
| 61 // (so that relocations accross llvm2ice and pnacl-llc will work). | |
| 62 virtual IceString mangleName(GlobalContext *Ctx) const = 0; | |
| 63 | |
| 64 protected: | |
| 65 GlobalDeclaration(GlobalDeclarationKind Kind) : Kind(Kind) {} | |
| 66 | |
| 67 const GlobalDeclarationKind Kind; | |
| 68 IceString Name; | |
| 69 }; | |
| 70 | |
| 71 // Models a function declaration. This includes the type signature of | |
| 72 // the function, its calling conventions, and its linkage. | |
| 73 class FunctionDeclaration : public GlobalDeclaration { | |
| 74 FunctionDeclaration(const FunctionDeclaration &) = delete; | |
| 75 FunctionDeclaration &operator=(const FunctionDeclaration &) = delete; | |
| 76 friend class GlobalContext; | |
| 77 | |
| 78 public: | |
| 79 static FunctionDeclaration *create(GlobalContext *Ctx, | |
| 80 const FuncSigType &Signature, | |
| 81 llvm::CallingConv::ID CallingConv, | |
| 82 llvm::GlobalValue::LinkageTypes Linkage, | |
| 83 bool IsProto); | |
| 84 ~FunctionDeclaration() final {} | |
| 85 const FuncSigType &getSignature() const { return Signature; } | |
| 86 llvm::CallingConv::ID getCallingConv() const { return CallingConv; } | |
| 87 llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; } | |
| 88 // isProto implies that there isn't a (local) definition for the function. | |
| 89 bool isProto() const { return IsProto; } | |
| 90 static bool classof(const GlobalDeclaration *Addr) { | |
| 91 return Addr->getKind() == FunctionDeclarationKind; | |
| 92 } | |
| 93 void dumpType(Ostream &Stream) const final; | |
| 94 void dump(Ostream &Stream) const final; | |
| 95 bool getIsExternal() const final { | |
| 96 return Linkage == llvm::GlobalValue::ExternalLinkage; | |
| 97 } | |
| 98 // bool hasInitializer() const final { return !IsProto; } | |
| 99 | |
| 100 virtual IceString mangleName(GlobalContext *Ctx) const final { | |
| 101 return (getIsExternal() && IsProto) ? Name : Ctx->mangleName(Name); | |
| 102 } | |
| 103 | |
| 104 private: | |
| 105 const Ice::FuncSigType Signature; | |
| 106 llvm::CallingConv::ID CallingConv; | |
| 107 llvm::GlobalValue::LinkageTypes Linkage; | |
| 108 bool IsProto; | |
| 109 | |
| 110 FunctionDeclaration(const FuncSigType &Signature, | |
| 111 llvm::CallingConv::ID CallingConv, | |
| 112 llvm::GlobalValue::LinkageTypes Linkage, bool IsProto) | |
| 113 : GlobalDeclaration(FunctionDeclarationKind), Signature(Signature), | |
| 114 CallingConv(CallingConv), Linkage(Linkage), IsProto(IsProto) {} | |
| 115 }; | |
| 116 | |
| 117 /// Models a global variable declaration, and its initializers. | |
| 118 class VariableDeclaration : public GlobalDeclaration { | |
| 119 VariableDeclaration(const VariableDeclaration &) = delete; | |
| 120 VariableDeclaration &operator=(const VariableDeclaration &) = delete; | |
| 121 friend class GlobalContext; | |
| 122 // TODO(kschimpf) Factor out allocation of initializers into the | |
| 123 // global context, so that memory allocation/collection can be | |
| 124 // optimized. | |
| 125 public: | |
| 34 /// Base class for a global variable initializer. | 126 /// Base class for a global variable initializer. |
| 35 class Initializer { | 127 class Initializer { |
| 36 Initializer(const Initializer &) = delete; | 128 Initializer(const Initializer &) = delete; |
| 37 Initializer &operator=(const Initializer &) = delete; | 129 Initializer &operator=(const Initializer &) = delete; |
| 38 | 130 |
| 39 public: | 131 public: |
| 40 /// Discriminator for LLVM-style RTTI. | 132 /// Discriminator for LLVM-style RTTI. |
| 41 enum InitializerKind { | 133 enum InitializerKind { |
| 42 DataInitializerKind, | 134 DataInitializerKind, |
| 43 ZeroInitializerKind, | 135 ZeroInitializerKind, |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 74 ++i; | 166 ++i; |
| 75 } | 167 } |
| 76 } | 168 } |
| 77 DataInitializer(const char *Str, size_t StrLen) | 169 DataInitializer(const char *Str, size_t StrLen) |
| 78 : Initializer(DataInitializerKind), Contents(StrLen) { | 170 : Initializer(DataInitializerKind), Contents(StrLen) { |
| 79 for (size_t i = 0; i < StrLen; ++i) | 171 for (size_t i = 0; i < StrLen; ++i) |
| 80 Contents[i] = static_cast<uint8_t>(Str[i]); | 172 Contents[i] = static_cast<uint8_t>(Str[i]); |
| 81 } | 173 } |
| 82 ~DataInitializer() override {} | 174 ~DataInitializer() override {} |
| 83 const DataVecType &getContents() const { return Contents; } | 175 const DataVecType &getContents() const { return Contents; } |
| 84 SizeT getNumBytes() const override { return Contents.size(); } | 176 SizeT getNumBytes() const final { return Contents.size(); } |
| 85 void dump(Ostream &Stream) const override; | 177 void dump(Ostream &Stream) const final; |
| 86 static bool classof(const Initializer *D) { | 178 static bool classof(const Initializer *D) { |
| 87 return D->getKind() == DataInitializerKind; | 179 return D->getKind() == DataInitializerKind; |
| 88 } | 180 } |
| 89 | 181 |
| 90 private: | 182 private: |
| 91 // The byte contents of the data initializer. | 183 // The byte contents of the data initializer. |
| 92 DataVecType Contents; | 184 DataVecType Contents; |
| 93 }; | 185 }; |
| 94 | 186 |
| 95 /// Defines a sequence of bytes initialized to zero. | 187 /// Defines a sequence of bytes initialized to zero. |
| 96 class ZeroInitializer : public Initializer { | 188 class ZeroInitializer : public Initializer { |
| 97 ZeroInitializer(const ZeroInitializer &) = delete; | 189 ZeroInitializer(const ZeroInitializer &) = delete; |
| 98 ZeroInitializer &operator=(const ZeroInitializer &) = delete; | 190 ZeroInitializer &operator=(const ZeroInitializer &) = delete; |
| 99 | 191 |
| 100 public: | 192 public: |
| 101 explicit ZeroInitializer(SizeT Size) | 193 explicit ZeroInitializer(SizeT Size) |
| 102 : Initializer(ZeroInitializerKind), Size(Size) {} | 194 : Initializer(ZeroInitializerKind), Size(Size) {} |
| 103 ~ZeroInitializer() override {} | 195 ~ZeroInitializer() override {} |
| 104 SizeT getNumBytes() const override { return Size; } | 196 SizeT getNumBytes() const final { return Size; } |
| 105 void dump(Ostream &Stream) const override; | 197 void dump(Ostream &Stream) const final; |
| 106 static bool classof(const Initializer *Z) { | 198 static bool classof(const Initializer *Z) { |
| 107 return Z->getKind() == ZeroInitializerKind; | 199 return Z->getKind() == ZeroInitializerKind; |
| 108 } | 200 } |
| 109 | 201 |
| 110 private: | 202 private: |
| 111 // The number of bytes to be zero initialized. | 203 // The number of bytes to be zero initialized. |
| 112 SizeT Size; | 204 SizeT Size; |
| 113 }; | 205 }; |
| 114 | 206 |
| 115 /// Defines the kind of relocation addresses allowed. | |
| 116 enum RelocationKind { FunctionRelocation, GlobalAddressRelocation }; | |
| 117 | |
| 118 /// Defines a relocation address (i.e. reference to a function | |
| 119 /// or global variable address). | |
| 120 class RelocationAddress { | |
| 121 RelocationAddress &operator=(const RelocationAddress &) = delete; | |
| 122 | |
| 123 public: | |
| 124 explicit RelocationAddress(const RelocationAddress &Addr) | |
| 125 : Kind(Addr.Kind) { | |
| 126 switch (Kind) { | |
| 127 case FunctionRelocation: | |
| 128 Address.Function = Addr.Address.Function; | |
| 129 break; | |
| 130 case GlobalAddressRelocation: | |
| 131 Address.GlobalAddr = Addr.Address.GlobalAddr; | |
| 132 } | |
| 133 } | |
| 134 explicit RelocationAddress(llvm::Value *Function) | |
| 135 : Kind(FunctionRelocation) { | |
| 136 Address.Function = Function; | |
| 137 } | |
| 138 explicit RelocationAddress(GlobalAddress *GlobalAddr) | |
| 139 : Kind(GlobalAddressRelocation) { | |
| 140 Address.GlobalAddr = GlobalAddr; | |
| 141 } | |
| 142 RelocationKind getKind() const { return Kind; } | |
| 143 llvm::Value *getFunction() const { | |
| 144 assert(Kind == FunctionRelocation); | |
| 145 return Address.Function; | |
| 146 } | |
| 147 GlobalAddress *getGlobalAddr() const { | |
| 148 assert(Kind == GlobalAddressRelocation); | |
| 149 return Address.GlobalAddr; | |
| 150 } | |
| 151 private: | |
| 152 const RelocationKind Kind; | |
| 153 union { | |
| 154 // TODO(kschimpf) Integrate Functions into ICE model. | |
| 155 llvm::Value *Function; | |
| 156 GlobalAddress *GlobalAddr; | |
| 157 } Address; | |
| 158 }; | |
| 159 | |
| 160 // Relocation address offsets must be 32 bit values. | 207 // Relocation address offsets must be 32 bit values. |
| 161 typedef int32_t RelocOffsetType; | 208 typedef int32_t RelocOffsetType; |
| 162 static const SizeT RelocAddrSize = 4; | 209 static const SizeT RelocAddrSize = 4; |
| 163 | 210 |
| 164 /// Defines the relocation value of another address. | 211 /// Defines the relocation value of another global declaration. |
| 165 class RelocInitializer : public Initializer { | 212 class RelocInitializer : public Initializer { |
| 166 RelocInitializer(const RelocInitializer &) = delete; | 213 RelocInitializer(const RelocInitializer &) = delete; |
| 167 RelocInitializer &operator=(const RelocInitializer &) = delete; | 214 RelocInitializer &operator=(const RelocInitializer &) = delete; |
| 168 | 215 |
| 169 public: | 216 public: |
| 170 RelocInitializer(const RelocationAddress &Address, RelocOffsetType Offset) | 217 RelocInitializer(const GlobalDeclaration *Declaration, |
| 171 : Initializer(RelocInitializerKind), Address(Address), Offset(Offset) {} | 218 RelocOffsetType Offset) |
| 219 : Initializer(RelocInitializerKind), Declaration(Declaration), | |
| 220 Offset(Offset) {} | |
| 172 ~RelocInitializer() override {} | 221 ~RelocInitializer() override {} |
| 173 RelocOffsetType getOffset() const { return Offset; } | 222 RelocOffsetType getOffset() const { return Offset; } |
| 174 IceString getName() const; | 223 const GlobalDeclaration *getDeclaration() const { return Declaration; } |
| 175 SizeT getNumBytes() const override { return RelocAddrSize; } | 224 SizeT getNumBytes() const final { return RelocAddrSize; } |
| 176 void dump(Ostream &Stream) const override; | 225 void dump(Ostream &Stream) const final; |
| 177 virtual void dumpType(Ostream &Stream) const; | 226 void dumpType(Ostream &Stream) const final; |
| 178 static bool classof(const Initializer *R) { | 227 static bool classof(const Initializer *R) { |
| 179 return R->getKind() == RelocInitializerKind; | 228 return R->getKind() == RelocInitializerKind; |
| 180 } | 229 } |
| 181 | 230 |
| 182 private: | 231 private: |
| 183 // The global address used in the relocation. | 232 // The global declaration used in the relocation. |
| 184 const RelocationAddress Address; | 233 const GlobalDeclaration *Declaration; |
| 185 // The offset to add to the relocation. | 234 // The offset to add to the relocation. |
| 186 const RelocOffsetType Offset; | 235 const RelocOffsetType Offset; |
| 187 }; | 236 }; |
| 188 | 237 |
| 189 /// Models the list of initializers. | 238 /// Models the list of initializers. |
| 190 typedef std::vector<Initializer *> InitializerListType; | 239 typedef std::vector<Initializer *> InitializerListType; |
| 191 | 240 |
| 192 GlobalAddress() : Alignment(0), IsConstant(false), IsInternal(true) {} | 241 static VariableDeclaration *create(GlobalContext *Ctx); |
| 193 ~GlobalAddress(); | 242 ~VariableDeclaration() final; |
| 194 | 243 |
| 195 const InitializerListType &getInitializers() const { return Initializers; } | 244 const InitializerListType &getInitializers() const { return Initializers; } |
| 196 bool hasName() const { return !Name.empty(); } | |
| 197 const IceString &getName() const { return Name; } | |
| 198 void setName(const IceString &NewName) { Name = NewName; } | |
| 199 bool getIsConstant() const { return IsConstant; } | 245 bool getIsConstant() const { return IsConstant; } |
| 200 void setIsConstant(bool NewValue) { IsConstant = NewValue; } | 246 void setIsConstant(bool NewValue) { IsConstant = NewValue; } |
| 201 uint32_t getAlignment() const { return Alignment; } | 247 uint32_t getAlignment() const { return Alignment; } |
| 202 void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; } | 248 void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; } |
| 203 bool getIsInternal() const { return IsInternal; } | 249 bool getIsInternal() const { return IsInternal; } |
| 204 void setIsInternal(bool NewValue) { IsInternal = NewValue; } | 250 void setIsInternal(bool NewValue) { IsInternal = NewValue; } |
| 251 bool getIsExternal() const final { return !getIsInternal(); } | |
| 252 bool hasInitializer() const { | |
| 253 return !(Initializers.size() == 1 && | |
| 254 llvm::isa<ZeroInitializer>(Initializers[0])); | |
| 255 } | |
| 205 | 256 |
| 206 /// Returns the number of bytes for the initializer of the global | 257 /// Returns the number of bytes for the initializer of the global |
| 207 /// address. | 258 /// address. |
| 208 SizeT getNumBytes() const { | 259 SizeT getNumBytes() const { |
| 209 SizeT Count = 0; | 260 SizeT Count = 0; |
| 210 for (Initializer *Init : Initializers) { | 261 for (Initializer *Init : Initializers) { |
| 211 Count += Init->getNumBytes(); | 262 Count += Init->getNumBytes(); |
| 212 } | 263 } |
| 213 return Count; | 264 return Count; |
| 214 } | 265 } |
| 215 | 266 |
| 216 /// Adds Initializer to the list of initializers. Takes ownership of | 267 /// Adds Initializer to the list of initializers. Takes ownership of |
| 217 /// the initializer. | 268 /// the initializer. |
| 218 void addInitializer(Initializer *Initializer) { | 269 void addInitializer(Initializer *Initializer) { |
| 219 Initializers.push_back(Initializer); | 270 Initializers.push_back(Initializer); |
| 220 } | 271 } |
| 221 | 272 |
| 222 /// Prints out type for initializer associated with the global address | 273 /// Prints out type for initializer associated with the declaration |
| 223 /// to Stream. | 274 /// to Stream. |
| 224 void dumpType(Ostream &Stream) const; | 275 void dumpType(Ostream &Stream) const final; |
| 225 | 276 |
| 226 /// Prints out the definition of the global address (including | 277 /// Prints out the definition of the global variable declaration |
| 227 /// initialization). | 278 /// (including initialization). |
| 228 void dump(Ostream &Stream) const; | 279 void dump(Ostream &Stream) const final; |
| 280 | |
| 281 static bool classof(const GlobalDeclaration *Addr) { | |
| 282 return Addr->getKind() == VariableDeclarationKind; | |
| 283 } | |
| 284 | |
| 285 IceString mangleName(GlobalContext *Ctx) const final { | |
| 286 return (getIsExternal() && !hasInitializer()) | |
| 287 ? Name : Ctx->mangleName(Name); | |
| 288 } | |
| 289 | |
| 229 | 290 |
| 230 private: | 291 private: |
| 231 // list of initializers associated with the global address. | 292 // list of initializers for the declared variable. |
| 232 InitializerListType Initializers; | 293 InitializerListType Initializers; |
| 233 // The name for the global. | 294 // The alignment of the declared variable. |
| 234 IceString Name; | |
| 235 // The alignment of the initializer. | |
| 236 uint32_t Alignment; | 295 uint32_t Alignment; |
| 237 // True if a constant initializer. | 296 // True if a declared (global) constant. |
| 238 bool IsConstant; | 297 bool IsConstant; |
| 239 // True if the address is internal. | 298 // True if the declaration is internal. |
| 240 bool IsInternal; | 299 bool IsInternal; |
| 300 | |
| 301 VariableDeclaration() | |
| 302 : GlobalDeclaration(VariableDeclarationKind), Alignment(0), | |
| 303 IsConstant(false), IsInternal(true) {} | |
| 241 }; | 304 }; |
| 242 | 305 |
| 243 template <class StreamType> | 306 template <class StreamType> |
| 244 inline StreamType &operator<<(StreamType &Stream, | 307 inline StreamType &operator<<(StreamType &Stream, |
| 245 const GlobalAddress::Initializer &Init) { | 308 const VariableDeclaration::Initializer &Init) { |
| 246 Init.dump(Stream); | 309 Init.dump(Stream); |
| 247 return Stream; | 310 return Stream; |
| 248 } | 311 } |
| 249 | 312 |
| 250 template <class StreamType> | 313 template <class StreamType> |
| 251 inline StreamType &operator<<(StreamType &Stream, const GlobalAddress &Addr) { | 314 inline StreamType &operator<<(StreamType &Stream, |
| 315 const GlobalDeclaration &Addr) { | |
| 252 Addr.dump(Stream); | 316 Addr.dump(Stream); |
| 253 return Stream; | 317 return Stream; |
| 254 } | 318 } |
| 255 | 319 |
| 256 } // end of namespace Ice | 320 } // end of namespace Ice |
| 257 | 321 |
| 258 #endif // SUBZERO_SRC_ICEGLOBALINITS_H | 322 #endif // SUBZERO_SRC_ICEGLOBALINITS_H |
| OLD | NEW |