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 |
| 20 #include "llvm/IR/CallingConv.h" |
| 21 #include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes |
| 22 |
19 #include "IceDefs.h" | 23 #include "IceDefs.h" |
| 24 #include "IceTypes.h" |
20 | 25 |
21 namespace llvm { | 26 // TODO(kschimpf): Remove ourselves from using LLVM representation for calling |
22 // TODO(kschimpf): Remove this dependency on LLVM IR. | 27 // conventions and linkage types. |
23 class Value; | |
24 } | |
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 /// Prints out type of the global declaration. |
| 52 virtual void dumpType(Ostream &Stream) const = 0; |
| 53 |
| 54 /// Prints out the global declaration. |
| 55 virtual void dump(Ostream &Stream) const = 0; |
| 56 |
| 57 // Mangles name for cross tests, unless external and not defined locally |
| 58 // (so that relocations accross llvm2ice and pnacl-llc will work). |
| 59 virtual IceString mangleName(GlobalContext *Ctx) const = 0; |
| 60 |
| 61 protected: |
| 62 GlobalDeclaration(GlobalDeclarationKind Kind) : Kind(Kind) {} |
| 63 |
| 64 const GlobalDeclarationKind Kind; |
| 65 IceString Name; |
| 66 }; |
| 67 |
| 68 // Models a function declaration. This includes the type signature of |
| 69 // the function, its calling conventions, and its linkage. |
| 70 class FunctionDeclaration : public GlobalDeclaration { |
| 71 FunctionDeclaration(const FunctionDeclaration &) = delete; |
| 72 FunctionDeclaration &operator=(const FunctionDeclaration &) = delete; |
| 73 friend class GlobalContext; |
| 74 |
| 75 public: |
| 76 static FunctionDeclaration *create(GlobalContext *Ctx, |
| 77 const FuncSigType &Signature, |
| 78 llvm::CallingConv::ID CallingConv, |
| 79 llvm::GlobalValue::LinkageTypes Linkage, |
| 80 bool IsProto); |
| 81 ~FunctionDeclaration() final {} |
| 82 const FuncSigType &getSignature() const { return Signature; } |
| 83 llvm::CallingConv::ID getCallingConv() const { return CallingConv; } |
| 84 llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; } |
| 85 // isProto implies that there isn't a (local) definition for the function. |
| 86 bool isProto() const { return IsProto; } |
| 87 static bool classof(const GlobalDeclaration *Addr) { |
| 88 return Addr->getKind() == FunctionDeclarationKind; |
| 89 } |
| 90 void dumpType(Ostream &Stream) const final; |
| 91 void dump(Ostream &Stream) const final; |
| 92 bool getIsExternal() const final { |
| 93 return Linkage == llvm::GlobalValue::ExternalLinkage; |
| 94 } |
| 95 |
| 96 virtual IceString mangleName(GlobalContext *Ctx) const final { |
| 97 return (getIsExternal() && IsProto) ? Name : Ctx->mangleName(Name); |
| 98 } |
| 99 |
| 100 private: |
| 101 const Ice::FuncSigType Signature; |
| 102 llvm::CallingConv::ID CallingConv; |
| 103 llvm::GlobalValue::LinkageTypes Linkage; |
| 104 bool IsProto; |
| 105 |
| 106 FunctionDeclaration(const FuncSigType &Signature, |
| 107 llvm::CallingConv::ID CallingConv, |
| 108 llvm::GlobalValue::LinkageTypes Linkage, bool IsProto) |
| 109 : GlobalDeclaration(FunctionDeclarationKind), Signature(Signature), |
| 110 CallingConv(CallingConv), Linkage(Linkage), IsProto(IsProto) {} |
| 111 }; |
| 112 |
| 113 /// Models a global variable declaration, and its initializers. |
| 114 class VariableDeclaration : public GlobalDeclaration { |
| 115 VariableDeclaration(const VariableDeclaration &) = delete; |
| 116 VariableDeclaration &operator=(const VariableDeclaration &) = delete; |
| 117 friend class GlobalContext; |
| 118 // TODO(kschimpf) Factor out allocation of initializers into the |
| 119 // global context, so that memory allocation/collection can be |
| 120 // optimized. |
| 121 public: |
34 /// Base class for a global variable initializer. | 122 /// Base class for a global variable initializer. |
35 class Initializer { | 123 class Initializer { |
36 Initializer(const Initializer &) = delete; | 124 Initializer(const Initializer &) = delete; |
37 Initializer &operator=(const Initializer &) = delete; | 125 Initializer &operator=(const Initializer &) = delete; |
38 | 126 |
39 public: | 127 public: |
40 /// Discriminator for LLVM-style RTTI. | 128 /// Discriminator for LLVM-style RTTI. |
41 enum InitializerKind { | 129 enum InitializerKind { |
42 DataInitializerKind, | 130 DataInitializerKind, |
43 ZeroInitializerKind, | 131 ZeroInitializerKind, |
(...skipping 30 matching lines...) Expand all Loading... |
74 ++i; | 162 ++i; |
75 } | 163 } |
76 } | 164 } |
77 DataInitializer(const char *Str, size_t StrLen) | 165 DataInitializer(const char *Str, size_t StrLen) |
78 : Initializer(DataInitializerKind), Contents(StrLen) { | 166 : Initializer(DataInitializerKind), Contents(StrLen) { |
79 for (size_t i = 0; i < StrLen; ++i) | 167 for (size_t i = 0; i < StrLen; ++i) |
80 Contents[i] = static_cast<uint8_t>(Str[i]); | 168 Contents[i] = static_cast<uint8_t>(Str[i]); |
81 } | 169 } |
82 ~DataInitializer() override {} | 170 ~DataInitializer() override {} |
83 const DataVecType &getContents() const { return Contents; } | 171 const DataVecType &getContents() const { return Contents; } |
84 SizeT getNumBytes() const override { return Contents.size(); } | 172 SizeT getNumBytes() const final { return Contents.size(); } |
85 void dump(Ostream &Stream) const override; | 173 void dump(Ostream &Stream) const final; |
86 static bool classof(const Initializer *D) { | 174 static bool classof(const Initializer *D) { |
87 return D->getKind() == DataInitializerKind; | 175 return D->getKind() == DataInitializerKind; |
88 } | 176 } |
89 | 177 |
90 private: | 178 private: |
91 // The byte contents of the data initializer. | 179 // The byte contents of the data initializer. |
92 DataVecType Contents; | 180 DataVecType Contents; |
93 }; | 181 }; |
94 | 182 |
95 /// Defines a sequence of bytes initialized to zero. | 183 /// Defines a sequence of bytes initialized to zero. |
96 class ZeroInitializer : public Initializer { | 184 class ZeroInitializer : public Initializer { |
97 ZeroInitializer(const ZeroInitializer &) = delete; | 185 ZeroInitializer(const ZeroInitializer &) = delete; |
98 ZeroInitializer &operator=(const ZeroInitializer &) = delete; | 186 ZeroInitializer &operator=(const ZeroInitializer &) = delete; |
99 | 187 |
100 public: | 188 public: |
101 explicit ZeroInitializer(SizeT Size) | 189 explicit ZeroInitializer(SizeT Size) |
102 : Initializer(ZeroInitializerKind), Size(Size) {} | 190 : Initializer(ZeroInitializerKind), Size(Size) {} |
103 ~ZeroInitializer() override {} | 191 ~ZeroInitializer() override {} |
104 SizeT getNumBytes() const override { return Size; } | 192 SizeT getNumBytes() const final { return Size; } |
105 void dump(Ostream &Stream) const override; | 193 void dump(Ostream &Stream) const final; |
106 static bool classof(const Initializer *Z) { | 194 static bool classof(const Initializer *Z) { |
107 return Z->getKind() == ZeroInitializerKind; | 195 return Z->getKind() == ZeroInitializerKind; |
108 } | 196 } |
109 | 197 |
110 private: | 198 private: |
111 // The number of bytes to be zero initialized. | 199 // The number of bytes to be zero initialized. |
112 SizeT Size; | 200 SizeT Size; |
113 }; | 201 }; |
114 | 202 |
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. | 203 // Relocation address offsets must be 32 bit values. |
161 typedef int32_t RelocOffsetType; | 204 typedef int32_t RelocOffsetType; |
162 static const SizeT RelocAddrSize = 4; | 205 static const SizeT RelocAddrSize = 4; |
163 | 206 |
164 /// Defines the relocation value of another address. | 207 /// Defines the relocation value of another global declaration. |
165 class RelocInitializer : public Initializer { | 208 class RelocInitializer : public Initializer { |
166 RelocInitializer(const RelocInitializer &) = delete; | 209 RelocInitializer(const RelocInitializer &) = delete; |
167 RelocInitializer &operator=(const RelocInitializer &) = delete; | 210 RelocInitializer &operator=(const RelocInitializer &) = delete; |
168 | 211 |
169 public: | 212 public: |
170 RelocInitializer(const RelocationAddress &Address, RelocOffsetType Offset) | 213 RelocInitializer(const GlobalDeclaration *Declaration, |
171 : Initializer(RelocInitializerKind), Address(Address), Offset(Offset) {} | 214 RelocOffsetType Offset) |
| 215 : Initializer(RelocInitializerKind), Declaration(Declaration), |
| 216 Offset(Offset) {} |
172 ~RelocInitializer() override {} | 217 ~RelocInitializer() override {} |
173 RelocOffsetType getOffset() const { return Offset; } | 218 RelocOffsetType getOffset() const { return Offset; } |
174 IceString getName() const; | 219 const GlobalDeclaration *getDeclaration() const { return Declaration; } |
175 SizeT getNumBytes() const override { return RelocAddrSize; } | 220 SizeT getNumBytes() const final { return RelocAddrSize; } |
176 void dump(Ostream &Stream) const override; | 221 void dump(Ostream &Stream) const final; |
177 virtual void dumpType(Ostream &Stream) const; | 222 void dumpType(Ostream &Stream) const final; |
178 static bool classof(const Initializer *R) { | 223 static bool classof(const Initializer *R) { |
179 return R->getKind() == RelocInitializerKind; | 224 return R->getKind() == RelocInitializerKind; |
180 } | 225 } |
181 | 226 |
182 private: | 227 private: |
183 // The global address used in the relocation. | 228 // The global declaration used in the relocation. |
184 const RelocationAddress Address; | 229 const GlobalDeclaration *Declaration; |
185 // The offset to add to the relocation. | 230 // The offset to add to the relocation. |
186 const RelocOffsetType Offset; | 231 const RelocOffsetType Offset; |
187 }; | 232 }; |
188 | 233 |
189 /// Models the list of initializers. | 234 /// Models the list of initializers. |
190 typedef std::vector<Initializer *> InitializerListType; | 235 typedef std::vector<Initializer *> InitializerListType; |
191 | 236 |
192 GlobalAddress() : Alignment(0), IsConstant(false), IsInternal(true) {} | 237 static VariableDeclaration *create(GlobalContext *Ctx); |
193 ~GlobalAddress(); | 238 ~VariableDeclaration() final; |
194 | 239 |
195 const InitializerListType &getInitializers() const { return Initializers; } | 240 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; } | 241 bool getIsConstant() const { return IsConstant; } |
200 void setIsConstant(bool NewValue) { IsConstant = NewValue; } | 242 void setIsConstant(bool NewValue) { IsConstant = NewValue; } |
201 uint32_t getAlignment() const { return Alignment; } | 243 uint32_t getAlignment() const { return Alignment; } |
202 void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; } | 244 void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; } |
203 bool getIsInternal() const { return IsInternal; } | 245 bool getIsInternal() const { return IsInternal; } |
204 void setIsInternal(bool NewValue) { IsInternal = NewValue; } | 246 void setIsInternal(bool NewValue) { IsInternal = NewValue; } |
| 247 bool getIsExternal() const final { return !getIsInternal(); } |
| 248 bool hasInitializer() const { |
| 249 return !(Initializers.size() == 1 && |
| 250 llvm::isa<ZeroInitializer>(Initializers[0])); |
| 251 } |
205 | 252 |
206 /// Returns the number of bytes for the initializer of the global | 253 /// Returns the number of bytes for the initializer of the global |
207 /// address. | 254 /// address. |
208 SizeT getNumBytes() const { | 255 SizeT getNumBytes() const { |
209 SizeT Count = 0; | 256 SizeT Count = 0; |
210 for (Initializer *Init : Initializers) { | 257 for (Initializer *Init : Initializers) { |
211 Count += Init->getNumBytes(); | 258 Count += Init->getNumBytes(); |
212 } | 259 } |
213 return Count; | 260 return Count; |
214 } | 261 } |
215 | 262 |
216 /// Adds Initializer to the list of initializers. Takes ownership of | 263 /// Adds Initializer to the list of initializers. Takes ownership of |
217 /// the initializer. | 264 /// the initializer. |
218 void addInitializer(Initializer *Initializer) { | 265 void addInitializer(Initializer *Initializer) { |
219 Initializers.push_back(Initializer); | 266 Initializers.push_back(Initializer); |
220 } | 267 } |
221 | 268 |
222 /// Prints out type for initializer associated with the global address | 269 /// Prints out type for initializer associated with the declaration |
223 /// to Stream. | 270 /// to Stream. |
224 void dumpType(Ostream &Stream) const; | 271 void dumpType(Ostream &Stream) const final; |
225 | 272 |
226 /// Prints out the definition of the global address (including | 273 /// Prints out the definition of the global variable declaration |
227 /// initialization). | 274 /// (including initialization). |
228 void dump(Ostream &Stream) const; | 275 void dump(Ostream &Stream) const final; |
| 276 |
| 277 static bool classof(const GlobalDeclaration *Addr) { |
| 278 return Addr->getKind() == VariableDeclarationKind; |
| 279 } |
| 280 |
| 281 IceString mangleName(GlobalContext *Ctx) const final { |
| 282 return (getIsExternal() && !hasInitializer()) |
| 283 ? Name : Ctx->mangleName(Name); |
| 284 } |
| 285 |
229 | 286 |
230 private: | 287 private: |
231 // list of initializers associated with the global address. | 288 // list of initializers for the declared variable. |
232 InitializerListType Initializers; | 289 InitializerListType Initializers; |
233 // The name for the global. | 290 // The alignment of the declared variable. |
234 IceString Name; | |
235 // The alignment of the initializer. | |
236 uint32_t Alignment; | 291 uint32_t Alignment; |
237 // True if a constant initializer. | 292 // True if a declared (global) constant. |
238 bool IsConstant; | 293 bool IsConstant; |
239 // True if the address is internal. | 294 // True if the declaration is internal. |
240 bool IsInternal; | 295 bool IsInternal; |
| 296 |
| 297 VariableDeclaration() |
| 298 : GlobalDeclaration(VariableDeclarationKind), Alignment(0), |
| 299 IsConstant(false), IsInternal(true) {} |
241 }; | 300 }; |
242 | 301 |
243 template <class StreamType> | 302 template <class StreamType> |
244 inline StreamType &operator<<(StreamType &Stream, | 303 inline StreamType &operator<<(StreamType &Stream, |
245 const GlobalAddress::Initializer &Init) { | 304 const VariableDeclaration::Initializer &Init) { |
246 Init.dump(Stream); | 305 Init.dump(Stream); |
247 return Stream; | 306 return Stream; |
248 } | 307 } |
249 | 308 |
250 template <class StreamType> | 309 template <class StreamType> |
251 inline StreamType &operator<<(StreamType &Stream, const GlobalAddress &Addr) { | 310 inline StreamType &operator<<(StreamType &Stream, |
| 311 const GlobalDeclaration &Addr) { |
252 Addr.dump(Stream); | 312 Addr.dump(Stream); |
253 return Stream; | 313 return Stream; |
254 } | 314 } |
255 | 315 |
256 } // end of namespace Ice | 316 } // end of namespace Ice |
257 | 317 |
258 #endif // SUBZERO_SRC_ICEGLOBALINITS_H | 318 #endif // SUBZERO_SRC_ICEGLOBALINITS_H |
OLD | NEW |