blob: 754f181d510ac47ced3185e384b04c1848ff249f [file] [log] [blame]
Karl Schimpf9d98d792014-10-13 15:01:08 -07001//===- subzero/src/IceGlobalInits.h - Global declarations -------*- C++ -*-===//
Karl Schimpfe3f64d02014-10-07 10:38:22 -07002//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Karl Schimpf9d98d792014-10-13 15:01:08 -070010// This file declares the representation of function declarations,
11// global variable declarations, and the corresponding variable
12// initializers in Subzero. Global variable initializers are
13// represented as a sequence of simple initializers.
Karl Schimpfe3f64d02014-10-07 10:38:22 -070014//
15//===----------------------------------------------------------------------===//
16
17#ifndef SUBZERO_SRC_ICEGLOBALINITS_H
18#define SUBZERO_SRC_ICEGLOBALINITS_H
19
Karl Schimpf9d98d792014-10-13 15:01:08 -070020#include "llvm/IR/CallingConv.h"
21#include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes
Karl Schimpfe3f64d02014-10-07 10:38:22 -070022
Karl Schimpf9d98d792014-10-13 15:01:08 -070023#include "IceDefs.h"
24#include "IceTypes.h"
25
26// TODO(kschimpf): Remove ourselves from using LLVM representation for calling
27// conventions and linkage types.
Karl Schimpfe3f64d02014-10-07 10:38:22 -070028
29namespace Ice {
30
Karl Schimpf9d98d792014-10-13 15:01:08 -070031/// Base class for global variable and function declarations.
32class GlobalDeclaration {
Jim Stichnothc6ead202015-02-24 09:30:30 -080033 GlobalDeclaration() = delete;
Karl Schimpf9d98d792014-10-13 15:01:08 -070034 GlobalDeclaration(const GlobalDeclaration &) = delete;
35 GlobalDeclaration &operator=(const GlobalDeclaration &) = delete;
Karl Schimpfe3f64d02014-10-07 10:38:22 -070036
37public:
Karl Schimpf9d98d792014-10-13 15:01:08 -070038 /// Discriminator for LLVM-style RTTI.
39 enum GlobalDeclarationKind {
40 FunctionDeclarationKind,
41 VariableDeclarationKind
42 };
43 GlobalDeclarationKind getKind() const { return Kind; }
44 const IceString &getName() const { return Name; }
45 void setName(const IceString &NewName) { Name = NewName; }
46 bool hasName() const { return !Name.empty(); }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070047 bool isInternal() const {
48 return Linkage == llvm::GlobalValue::InternalLinkage;
49 }
50 llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; }
51 bool isExternal() const {
52 return Linkage == llvm::GlobalValue::ExternalLinkage;
53 }
54 void setLinkage(llvm::GlobalValue::LinkageTypes NewLinkage) {
55 Linkage = NewLinkage;
56 }
Karl Schimpf9d98d792014-10-13 15:01:08 -070057 virtual ~GlobalDeclaration() {}
58
Karl Schimpf9d98d792014-10-13 15:01:08 -070059 /// Prints out type of the global declaration.
60 virtual void dumpType(Ostream &Stream) const = 0;
61
62 /// Prints out the global declaration.
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070063 virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0;
64 void dump(Ostream &Stream) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -080065 if (!ALLOW_DUMP)
66 return;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070067 GlobalContext *const Ctx = nullptr;
68 dump(Ctx, Stream);
69 }
70
71 /// Returns true if when emitting names, we should suppress mangling.
72 virtual bool getSuppressMangling() const = 0;
Karl Schimpf9d98d792014-10-13 15:01:08 -070073
74 // Mangles name for cross tests, unless external and not defined locally
Jim Stichnothfa0cfa52015-02-26 09:42:36 -080075 // (so that relocations accross pnacl-sz and pnacl-llc will work).
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070076 virtual IceString mangleName(GlobalContext *Ctx) const {
77 return getSuppressMangling() ? Name : Ctx->mangleName(Name);
78 }
Karl Schimpf9d98d792014-10-13 15:01:08 -070079
80protected:
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070081 GlobalDeclaration(GlobalDeclarationKind Kind,
82 llvm::GlobalValue::LinkageTypes Linkage)
83 : Kind(Kind), Linkage(Linkage) {}
Karl Schimpf9d98d792014-10-13 15:01:08 -070084
85 const GlobalDeclarationKind Kind;
86 IceString Name;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070087 llvm::GlobalValue::LinkageTypes Linkage;
Karl Schimpf9d98d792014-10-13 15:01:08 -070088};
89
90// Models a function declaration. This includes the type signature of
91// the function, its calling conventions, and its linkage.
92class FunctionDeclaration : public GlobalDeclaration {
Jim Stichnothc6ead202015-02-24 09:30:30 -080093 FunctionDeclaration() = delete;
Karl Schimpf9d98d792014-10-13 15:01:08 -070094 FunctionDeclaration(const FunctionDeclaration &) = delete;
95 FunctionDeclaration &operator=(const FunctionDeclaration &) = delete;
Karl Schimpf9d98d792014-10-13 15:01:08 -070096
97public:
Jim Stichnotha086b912015-01-20 14:53:57 -080098 static FunctionDeclaration *create(const FuncSigType &Signature,
Karl Schimpf9d98d792014-10-13 15:01:08 -070099 llvm::CallingConv::ID CallingConv,
100 llvm::GlobalValue::LinkageTypes Linkage,
101 bool IsProto);
102 ~FunctionDeclaration() final {}
103 const FuncSigType &getSignature() const { return Signature; }
104 llvm::CallingConv::ID getCallingConv() const { return CallingConv; }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700105 // isProto implies that there isn't a (local) definition for the function.
106 bool isProto() const { return IsProto; }
107 static bool classof(const GlobalDeclaration *Addr) {
108 return Addr->getKind() == FunctionDeclarationKind;
109 }
110 void dumpType(Ostream &Stream) const final;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700111 void dump(GlobalContext *Ctx, Ostream &Stream) const final;
Jim Stichnothdd842db2015-01-27 12:53:53 -0800112 bool getSuppressMangling() const final { return isExternal() && IsProto; }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700113
114private:
115 const Ice::FuncSigType Signature;
116 llvm::CallingConv::ID CallingConv;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700117 bool IsProto;
118
119 FunctionDeclaration(const FuncSigType &Signature,
120 llvm::CallingConv::ID CallingConv,
121 llvm::GlobalValue::LinkageTypes Linkage, bool IsProto)
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700122 : GlobalDeclaration(FunctionDeclarationKind, Linkage),
123 Signature(Signature), CallingConv(CallingConv), IsProto(IsProto) {}
Karl Schimpf9d98d792014-10-13 15:01:08 -0700124};
125
126/// Models a global variable declaration, and its initializers.
127class VariableDeclaration : public GlobalDeclaration {
128 VariableDeclaration(const VariableDeclaration &) = delete;
129 VariableDeclaration &operator=(const VariableDeclaration &) = delete;
Jim Stichnothdd842db2015-01-27 12:53:53 -0800130
Karl Schimpf9d98d792014-10-13 15:01:08 -0700131public:
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700132 /// Base class for a global variable initializer.
133 class Initializer {
134 Initializer(const Initializer &) = delete;
135 Initializer &operator=(const Initializer &) = delete;
136
137 public:
138 /// Discriminator for LLVM-style RTTI.
139 enum InitializerKind {
140 DataInitializerKind,
141 ZeroInitializerKind,
142 RelocInitializerKind
143 };
144 InitializerKind getKind() const { return Kind; }
145 virtual ~Initializer() {}
146 virtual SizeT getNumBytes() const = 0;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700147 virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0;
148 void dump(Ostream &Stream) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800149 if (ALLOW_DUMP)
150 dump(nullptr, Stream);
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700151 }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700152 virtual void dumpType(Ostream &Stream) const;
153
154 protected:
155 explicit Initializer(InitializerKind Kind) : Kind(Kind) {}
156
157 private:
158 const InitializerKind Kind;
159 };
160
161 // Models the data in a data initializer.
Jan Voung72984d82015-01-29 14:42:38 -0800162 typedef std::vector<char> DataVecType;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700163
164 /// Defines a sequence of byte values as a data initializer.
165 class DataInitializer : public Initializer {
166 DataInitializer(const DataInitializer &) = delete;
167 DataInitializer &operator=(const DataInitializer &) = delete;
168
169 public:
170 template <class IntContainer>
171 DataInitializer(const IntContainer &Values)
172 : Initializer(DataInitializerKind), Contents(Values.size()) {
173 size_t i = 0;
174 for (auto &V : Values) {
Jan Voung72984d82015-01-29 14:42:38 -0800175 Contents[i] = static_cast<int8_t>(V);
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700176 ++i;
177 }
178 }
179 DataInitializer(const char *Str, size_t StrLen)
180 : Initializer(DataInitializerKind), Contents(StrLen) {
181 for (size_t i = 0; i < StrLen; ++i)
Jan Voung72984d82015-01-29 14:42:38 -0800182 Contents[i] = Str[i];
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700183 }
184 ~DataInitializer() override {}
185 const DataVecType &getContents() const { return Contents; }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700186 SizeT getNumBytes() const final { return Contents.size(); }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700187 void dump(GlobalContext *Ctx, Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700188 static bool classof(const Initializer *D) {
189 return D->getKind() == DataInitializerKind;
190 }
191
192 private:
193 // The byte contents of the data initializer.
194 DataVecType Contents;
195 };
196
197 /// Defines a sequence of bytes initialized to zero.
198 class ZeroInitializer : public Initializer {
199 ZeroInitializer(const ZeroInitializer &) = delete;
200 ZeroInitializer &operator=(const ZeroInitializer &) = delete;
201
202 public:
203 explicit ZeroInitializer(SizeT Size)
204 : Initializer(ZeroInitializerKind), Size(Size) {}
205 ~ZeroInitializer() override {}
Karl Schimpf9d98d792014-10-13 15:01:08 -0700206 SizeT getNumBytes() const final { return Size; }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700207 void dump(GlobalContext *Ctx, Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700208 static bool classof(const Initializer *Z) {
209 return Z->getKind() == ZeroInitializerKind;
210 }
211
212 private:
213 // The number of bytes to be zero initialized.
214 SizeT Size;
215 };
216
Karl Schimpf9d98d792014-10-13 15:01:08 -0700217 /// Defines the relocation value of another global declaration.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700218 class RelocInitializer : public Initializer {
219 RelocInitializer(const RelocInitializer &) = delete;
220 RelocInitializer &operator=(const RelocInitializer &) = delete;
221
222 public:
Jan Voungc0d965f2014-11-04 16:55:01 -0800223 RelocInitializer(const GlobalDeclaration *Declaration, RelocOffsetT Offset)
Karl Schimpf9d98d792014-10-13 15:01:08 -0700224 : Initializer(RelocInitializerKind), Declaration(Declaration),
225 Offset(Offset) {}
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700226 ~RelocInitializer() override {}
Jan Voungc0d965f2014-11-04 16:55:01 -0800227 RelocOffsetT getOffset() const { return Offset; }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700228 const GlobalDeclaration *getDeclaration() const { return Declaration; }
229 SizeT getNumBytes() const final { return RelocAddrSize; }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700230 void dump(GlobalContext *Ctx, Ostream &Stream) const final;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700231 void dumpType(Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700232 static bool classof(const Initializer *R) {
233 return R->getKind() == RelocInitializerKind;
234 }
235
236 private:
Karl Schimpf9d98d792014-10-13 15:01:08 -0700237 // The global declaration used in the relocation.
238 const GlobalDeclaration *Declaration;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700239 // The offset to add to the relocation.
Jan Voungc0d965f2014-11-04 16:55:01 -0800240 const RelocOffsetT Offset;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700241 };
242
243 /// Models the list of initializers.
244 typedef std::vector<Initializer *> InitializerListType;
245
Jim Stichnotha086b912015-01-20 14:53:57 -0800246 static VariableDeclaration *create();
Karl Schimpf9d98d792014-10-13 15:01:08 -0700247 ~VariableDeclaration() final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700248
249 const InitializerListType &getInitializers() const { return Initializers; }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700250 bool getIsConstant() const { return IsConstant; }
251 void setIsConstant(bool NewValue) { IsConstant = NewValue; }
252 uint32_t getAlignment() const { return Alignment; }
253 void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700254 bool hasInitializer() const { return !Initializers.empty(); }
255 bool hasNonzeroInitializer() const {
Karl Schimpf9d98d792014-10-13 15:01:08 -0700256 return !(Initializers.size() == 1 &&
257 llvm::isa<ZeroInitializer>(Initializers[0]));
258 }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700259
260 /// Returns the number of bytes for the initializer of the global
261 /// address.
262 SizeT getNumBytes() const {
263 SizeT Count = 0;
264 for (Initializer *Init : Initializers) {
265 Count += Init->getNumBytes();
266 }
267 return Count;
268 }
269
270 /// Adds Initializer to the list of initializers. Takes ownership of
271 /// the initializer.
272 void addInitializer(Initializer *Initializer) {
273 Initializers.push_back(Initializer);
274 }
275
Karl Schimpf9d98d792014-10-13 15:01:08 -0700276 /// Prints out type for initializer associated with the declaration
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700277 /// to Stream.
Karl Schimpf9d98d792014-10-13 15:01:08 -0700278 void dumpType(Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700279
Karl Schimpf9d98d792014-10-13 15:01:08 -0700280 /// Prints out the definition of the global variable declaration
281 /// (including initialization).
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700282 void dump(GlobalContext *Ctx, Ostream &Stream) const final;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700283
284 static bool classof(const GlobalDeclaration *Addr) {
285 return Addr->getKind() == VariableDeclarationKind;
286 }
287
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700288 bool getSuppressMangling() const final {
Jim Stichnothd9f1f9f2015-06-11 10:19:32 -0700289 if (ForceSuppressMangling)
290 return true;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700291 return isExternal() && !hasInitializer();
Karl Schimpf9d98d792014-10-13 15:01:08 -0700292 }
293
Jim Stichnoth0933c0c2015-06-12 10:41:16 -0700294 void setSuppressMangling() { ForceSuppressMangling = true; }
Jim Stichnothd9f1f9f2015-06-11 10:19:32 -0700295
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700296private:
Karl Schimpf9d98d792014-10-13 15:01:08 -0700297 // list of initializers for the declared variable.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700298 InitializerListType Initializers;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700299 // The alignment of the declared variable.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700300 uint32_t Alignment;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700301 // True if a declared (global) constant.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700302 bool IsConstant;
Jim Stichnothd9f1f9f2015-06-11 10:19:32 -0700303 // If set to true, force getSuppressMangling() to return true.
304 bool ForceSuppressMangling;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700305
306 VariableDeclaration()
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700307 : GlobalDeclaration(VariableDeclarationKind,
308 llvm::GlobalValue::InternalLinkage),
Jim Stichnothd9f1f9f2015-06-11 10:19:32 -0700309 Alignment(0), IsConstant(false), ForceSuppressMangling(false) {}
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700310};
311
312template <class StreamType>
313inline StreamType &operator<<(StreamType &Stream,
Karl Schimpf9d98d792014-10-13 15:01:08 -0700314 const VariableDeclaration::Initializer &Init) {
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700315 Init.dump(Stream);
316 return Stream;
317}
318
319template <class StreamType>
Karl Schimpf9d98d792014-10-13 15:01:08 -0700320inline StreamType &operator<<(StreamType &Stream,
321 const GlobalDeclaration &Addr) {
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700322 Addr.dump(Stream);
323 return Stream;
324}
325
326} // end of namespace Ice
327
328#endif // SUBZERO_SRC_ICEGLOBALINITS_H