blob: c15aed00ec3e9bf94b091ef0069d286afac5f95b [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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
11/// This file declares the representation of function declarations,
12/// global variable declarations, and the corresponding variable
13/// initializers in Subzero. Global variable initializers are
14/// represented as a sequence of simple initializers.
15///
Karl Schimpfe3f64d02014-10-07 10:38:22 -070016//===----------------------------------------------------------------------===//
17
18#ifndef SUBZERO_SRC_ICEGLOBALINITS_H
19#define SUBZERO_SRC_ICEGLOBALINITS_H
20
John Porto67f8de92015-06-25 10:14:17 -070021#include "IceDefs.h"
22#include "IceGlobalContext.h"
23#include "IceTypes.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070024
25#pragma clang diagnostic push
26#pragma clang diagnostic ignored "-Wunused-parameter"
Andrew Scull2c688f62015-09-09 11:56:10 -070027#pragma clang diagnostic ignored "-Wredundant-move"
John Porto1bec8bc2015-06-22 10:51:13 -070028#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" // for NaClBitcodeRecord.
Karl Schimpf9d98d792014-10-13 15:01:08 -070029#include "llvm/IR/CallingConv.h"
John Porto1bec8bc2015-06-22 10:51:13 -070030#include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes.
Jim Stichnoth98da9662015-06-27 06:38:08 -070031#pragma clang diagnostic pop
Karl Schimpfe3f64d02014-10-07 10:38:22 -070032
John Porto67f8de92015-06-25 10:14:17 -070033#include <memory>
34#include <utility>
Karl Schimpf9d98d792014-10-13 15:01:08 -070035
36// TODO(kschimpf): Remove ourselves from using LLVM representation for calling
37// conventions and linkage types.
Karl Schimpfe3f64d02014-10-07 10:38:22 -070038
39namespace Ice {
40
Karl Schimpf9d98d792014-10-13 15:01:08 -070041/// Base class for global variable and function declarations.
42class GlobalDeclaration {
Jim Stichnothc6ead202015-02-24 09:30:30 -080043 GlobalDeclaration() = delete;
Karl Schimpf9d98d792014-10-13 15:01:08 -070044 GlobalDeclaration(const GlobalDeclaration &) = delete;
45 GlobalDeclaration &operator=(const GlobalDeclaration &) = delete;
Karl Schimpfe3f64d02014-10-07 10:38:22 -070046
47public:
Karl Schimpf9d98d792014-10-13 15:01:08 -070048 /// Discriminator for LLVM-style RTTI.
49 enum GlobalDeclarationKind {
50 FunctionDeclarationKind,
51 VariableDeclarationKind
52 };
53 GlobalDeclarationKind getKind() const { return Kind; }
54 const IceString &getName() const { return Name; }
55 void setName(const IceString &NewName) { Name = NewName; }
56 bool hasName() const { return !Name.empty(); }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070057 bool isInternal() const {
58 return Linkage == llvm::GlobalValue::InternalLinkage;
59 }
60 llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; }
61 bool isExternal() const {
62 return Linkage == llvm::GlobalValue::ExternalLinkage;
63 }
64 void setLinkage(llvm::GlobalValue::LinkageTypes NewLinkage) {
65 Linkage = NewLinkage;
66 }
Jim Stichnotheafb56c2015-06-22 10:35:22 -070067 virtual ~GlobalDeclaration() = default;
Karl Schimpf9d98d792014-10-13 15:01:08 -070068
Karl Schimpf9d98d792014-10-13 15:01:08 -070069 /// Prints out type of the global declaration.
70 virtual void dumpType(Ostream &Stream) const = 0;
71
72 /// Prints out the global declaration.
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070073 virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0;
74 void dump(Ostream &Stream) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070075 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -080076 return;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070077 GlobalContext *const Ctx = nullptr;
78 dump(Ctx, Stream);
79 }
80
81 /// Returns true if when emitting names, we should suppress mangling.
82 virtual bool getSuppressMangling() const = 0;
Karl Schimpf9d98d792014-10-13 15:01:08 -070083
Andrew Scull9612d322015-07-06 14:53:25 -070084 /// Mangles name for cross tests, unless external and not defined locally
85 /// (so that relocations accross pnacl-sz and pnacl-llc will work).
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070086 virtual IceString mangleName(GlobalContext *Ctx) const {
87 return getSuppressMangling() ? Name : Ctx->mangleName(Name);
88 }
Karl Schimpf9d98d792014-10-13 15:01:08 -070089
90protected:
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070091 GlobalDeclaration(GlobalDeclarationKind Kind,
92 llvm::GlobalValue::LinkageTypes Linkage)
93 : Kind(Kind), Linkage(Linkage) {}
Karl Schimpf9d98d792014-10-13 15:01:08 -070094
95 const GlobalDeclarationKind Kind;
96 IceString Name;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070097 llvm::GlobalValue::LinkageTypes Linkage;
Karl Schimpf9d98d792014-10-13 15:01:08 -070098};
99
Andrew Scull9612d322015-07-06 14:53:25 -0700100/// Models a function declaration. This includes the type signature of
101/// the function, its calling conventions, and its linkage.
Karl Schimpf9d98d792014-10-13 15:01:08 -0700102class FunctionDeclaration : public GlobalDeclaration {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800103 FunctionDeclaration() = delete;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700104 FunctionDeclaration(const FunctionDeclaration &) = delete;
105 FunctionDeclaration &operator=(const FunctionDeclaration &) = delete;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700106
107public:
John Porto1bec8bc2015-06-22 10:51:13 -0700108 static FunctionDeclaration *create(GlobalContext *Context,
109 const FuncSigType &Signature,
Karl Schimpf9d98d792014-10-13 15:01:08 -0700110 llvm::CallingConv::ID CallingConv,
111 llvm::GlobalValue::LinkageTypes Linkage,
John Porto1bec8bc2015-06-22 10:51:13 -0700112 bool IsProto) {
113 return new (Context->allocate<FunctionDeclaration>())
114 FunctionDeclaration(Signature, CallingConv, Linkage, IsProto);
115 }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700116 const FuncSigType &getSignature() const { return Signature; }
117 llvm::CallingConv::ID getCallingConv() const { return CallingConv; }
Andrew Scull9612d322015-07-06 14:53:25 -0700118 /// isProto implies that there isn't a (local) definition for the function.
Karl Schimpf9d98d792014-10-13 15:01:08 -0700119 bool isProto() const { return IsProto; }
120 static bool classof(const GlobalDeclaration *Addr) {
121 return Addr->getKind() == FunctionDeclarationKind;
122 }
123 void dumpType(Ostream &Stream) const final;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700124 void dump(GlobalContext *Ctx, Ostream &Stream) const final;
Jim Stichnothdd842db2015-01-27 12:53:53 -0800125 bool getSuppressMangling() const final { return isExternal() && IsProto; }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700126
127private:
128 const Ice::FuncSigType Signature;
129 llvm::CallingConv::ID CallingConv;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700130 bool IsProto;
131
132 FunctionDeclaration(const FuncSigType &Signature,
133 llvm::CallingConv::ID CallingConv,
134 llvm::GlobalValue::LinkageTypes Linkage, bool IsProto)
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700135 : GlobalDeclaration(FunctionDeclarationKind, Linkage),
136 Signature(Signature), CallingConv(CallingConv), IsProto(IsProto) {}
Karl Schimpf9d98d792014-10-13 15:01:08 -0700137};
138
139/// Models a global variable declaration, and its initializers.
140class VariableDeclaration : public GlobalDeclaration {
141 VariableDeclaration(const VariableDeclaration &) = delete;
142 VariableDeclaration &operator=(const VariableDeclaration &) = delete;
Jim Stichnothdd842db2015-01-27 12:53:53 -0800143
Karl Schimpf9d98d792014-10-13 15:01:08 -0700144public:
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700145 /// Base class for a global variable initializer.
146 class Initializer {
147 Initializer(const Initializer &) = delete;
148 Initializer &operator=(const Initializer &) = delete;
149
150 public:
151 /// Discriminator for LLVM-style RTTI.
152 enum InitializerKind {
153 DataInitializerKind,
154 ZeroInitializerKind,
155 RelocInitializerKind
156 };
157 InitializerKind getKind() const { return Kind; }
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700158 virtual ~Initializer() = default;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700159 virtual SizeT getNumBytes() const = 0;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700160 virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0;
161 void dump(Ostream &Stream) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700162 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800163 dump(nullptr, Stream);
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700164 }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700165 virtual void dumpType(Ostream &Stream) const;
166
167 protected:
168 explicit Initializer(InitializerKind Kind) : Kind(Kind) {}
169
170 private:
171 const InitializerKind Kind;
172 };
173
Andrew Scull9612d322015-07-06 14:53:25 -0700174 /// Models the data in a data initializer.
Andrew Scull8072bae2015-09-14 16:01:26 -0700175 using DataVecType = std::vector<char>;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700176
177 /// Defines a sequence of byte values as a data initializer.
178 class DataInitializer : public Initializer {
179 DataInitializer(const DataInitializer &) = delete;
180 DataInitializer &operator=(const DataInitializer &) = delete;
181
182 public:
John Porto1bec8bc2015-06-22 10:51:13 -0700183 template <class... Args>
184 static std::unique_ptr<DataInitializer> create(Args &&... TheArgs) {
185 return makeUnique<DataInitializer>(std::forward<Args>(TheArgs)...);
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700186 }
John Porto1bec8bc2015-06-22 10:51:13 -0700187
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700188 const DataVecType &getContents() const { return Contents; }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700189 SizeT getNumBytes() const final { return Contents.size(); }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700190 void dump(GlobalContext *Ctx, Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700191 static bool classof(const Initializer *D) {
192 return D->getKind() == DataInitializerKind;
193 }
194
195 private:
John Porto1bec8bc2015-06-22 10:51:13 -0700196 ENABLE_MAKE_UNIQUE;
197
198 DataInitializer(const llvm::NaClBitcodeRecord::RecordVector &Values)
199 : Initializer(DataInitializerKind), Contents(Values.size()) {
200 for (SizeT I = 0; I < Values.size(); ++I)
201 Contents[I] = static_cast<int8_t>(Values[I]);
202 }
203
204 DataInitializer(const char *Str, size_t StrLen)
205 : Initializer(DataInitializerKind), Contents(StrLen) {
206 for (size_t i = 0; i < StrLen; ++i)
207 Contents[i] = Str[i];
208 }
209
Andrew Scull9612d322015-07-06 14:53:25 -0700210 /// The byte contents of the data initializer.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700211 DataVecType Contents;
212 };
213
214 /// Defines a sequence of bytes initialized to zero.
215 class ZeroInitializer : public Initializer {
216 ZeroInitializer(const ZeroInitializer &) = delete;
217 ZeroInitializer &operator=(const ZeroInitializer &) = delete;
218
219 public:
John Porto1bec8bc2015-06-22 10:51:13 -0700220 static std::unique_ptr<ZeroInitializer> create(SizeT Size) {
221 return makeUnique<ZeroInitializer>(Size);
222 }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700223 SizeT getNumBytes() const final { return Size; }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700224 void dump(GlobalContext *Ctx, Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700225 static bool classof(const Initializer *Z) {
226 return Z->getKind() == ZeroInitializerKind;
227 }
228
229 private:
John Porto1bec8bc2015-06-22 10:51:13 -0700230 ENABLE_MAKE_UNIQUE;
231
232 explicit ZeroInitializer(SizeT Size)
233 : Initializer(ZeroInitializerKind), Size(Size) {}
234
Andrew Scull9612d322015-07-06 14:53:25 -0700235 /// The number of bytes to be zero initialized.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700236 SizeT Size;
237 };
238
Karl Schimpf9d98d792014-10-13 15:01:08 -0700239 /// Defines the relocation value of another global declaration.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700240 class RelocInitializer : public Initializer {
241 RelocInitializer(const RelocInitializer &) = delete;
242 RelocInitializer &operator=(const RelocInitializer &) = delete;
243
244 public:
John Porto1bec8bc2015-06-22 10:51:13 -0700245 static std::unique_ptr<RelocInitializer>
246 create(const GlobalDeclaration *Declaration, RelocOffsetT Offset) {
247 return makeUnique<RelocInitializer>(Declaration, Offset);
248 }
249
Jan Voungc0d965f2014-11-04 16:55:01 -0800250 RelocOffsetT getOffset() const { return Offset; }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700251 const GlobalDeclaration *getDeclaration() const { return Declaration; }
252 SizeT getNumBytes() const final { return RelocAddrSize; }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700253 void dump(GlobalContext *Ctx, Ostream &Stream) const final;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700254 void dumpType(Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700255 static bool classof(const Initializer *R) {
256 return R->getKind() == RelocInitializerKind;
257 }
258
259 private:
John Porto1bec8bc2015-06-22 10:51:13 -0700260 ENABLE_MAKE_UNIQUE;
261
262 RelocInitializer(const GlobalDeclaration *Declaration, RelocOffsetT Offset)
263 : Initializer(RelocInitializerKind), Declaration(Declaration),
264 Offset(Offset) {} // The global declaration used in the relocation.
265
Karl Schimpf9d98d792014-10-13 15:01:08 -0700266 const GlobalDeclaration *Declaration;
Andrew Scull9612d322015-07-06 14:53:25 -0700267 /// The offset to add to the relocation.
Jan Voungc0d965f2014-11-04 16:55:01 -0800268 const RelocOffsetT Offset;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700269 };
270
271 /// Models the list of initializers.
Andrew Scull8072bae2015-09-14 16:01:26 -0700272 using InitializerListType = std::vector<std::unique_ptr<Initializer>>;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700273
John Porto1bec8bc2015-06-22 10:51:13 -0700274 static VariableDeclaration *create(GlobalContext *Context) {
275 return new (Context->allocate<VariableDeclaration>()) VariableDeclaration();
276 }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700277
John Porto1bec8bc2015-06-22 10:51:13 -0700278 const InitializerListType &getInitializers() const { return *Initializers; }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700279 bool getIsConstant() const { return IsConstant; }
280 void setIsConstant(bool NewValue) { IsConstant = NewValue; }
281 uint32_t getAlignment() const { return Alignment; }
282 void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; }
John Porto1bec8bc2015-06-22 10:51:13 -0700283 bool hasInitializer() const { return HasInitializer; }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700284 bool hasNonzeroInitializer() const {
John Porto1bec8bc2015-06-22 10:51:13 -0700285 return !(Initializers->size() == 1 &&
286 llvm::isa<ZeroInitializer>((*Initializers)[0].get()));
Karl Schimpf9d98d792014-10-13 15:01:08 -0700287 }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700288
289 /// Returns the number of bytes for the initializer of the global
290 /// address.
291 SizeT getNumBytes() const {
292 SizeT Count = 0;
John Porto1bec8bc2015-06-22 10:51:13 -0700293 for (const std::unique_ptr<Initializer> &Init : *Initializers) {
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700294 Count += Init->getNumBytes();
295 }
296 return Count;
297 }
298
299 /// Adds Initializer to the list of initializers. Takes ownership of
300 /// the initializer.
John Porto1bec8bc2015-06-22 10:51:13 -0700301 void addInitializer(std::unique_ptr<Initializer> Initializer) {
302 Initializers->emplace_back(std::move(Initializer));
303 HasInitializer = true;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700304 }
305
Karl Schimpf9d98d792014-10-13 15:01:08 -0700306 /// Prints out type for initializer associated with the declaration
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700307 /// to Stream.
Karl Schimpf9d98d792014-10-13 15:01:08 -0700308 void dumpType(Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700309
Karl Schimpf9d98d792014-10-13 15:01:08 -0700310 /// Prints out the definition of the global variable declaration
311 /// (including initialization).
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700312 void dump(GlobalContext *Ctx, Ostream &Stream) const final;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700313
314 static bool classof(const GlobalDeclaration *Addr) {
315 return Addr->getKind() == VariableDeclarationKind;
316 }
317
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700318 bool getSuppressMangling() const final {
Jim Stichnothd9f1f9f2015-06-11 10:19:32 -0700319 if (ForceSuppressMangling)
320 return true;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700321 return isExternal() && !hasInitializer();
Karl Schimpf9d98d792014-10-13 15:01:08 -0700322 }
323
Jim Stichnoth0933c0c2015-06-12 10:41:16 -0700324 void setSuppressMangling() { ForceSuppressMangling = true; }
Jim Stichnothd9f1f9f2015-06-11 10:19:32 -0700325
John Porto1bec8bc2015-06-22 10:51:13 -0700326 void discardInitializers() { Initializers = nullptr; }
327
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700328private:
Andrew Scull9612d322015-07-06 14:53:25 -0700329 /// List of initializers for the declared variable.
John Porto1bec8bc2015-06-22 10:51:13 -0700330 std::unique_ptr<InitializerListType> Initializers;
331 bool HasInitializer;
Andrew Scull9612d322015-07-06 14:53:25 -0700332 /// The alignment of the declared variable.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700333 uint32_t Alignment;
Andrew Scull9612d322015-07-06 14:53:25 -0700334 /// True if a declared (global) constant.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700335 bool IsConstant;
Andrew Scull9612d322015-07-06 14:53:25 -0700336 /// If set to true, force getSuppressMangling() to return true.
Jim Stichnothd9f1f9f2015-06-11 10:19:32 -0700337 bool ForceSuppressMangling;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700338
339 VariableDeclaration()
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700340 : GlobalDeclaration(VariableDeclarationKind,
341 llvm::GlobalValue::InternalLinkage),
John Porto1bec8bc2015-06-22 10:51:13 -0700342 Initializers(new InitializerListType), HasInitializer(false),
Jim Stichnothd9f1f9f2015-06-11 10:19:32 -0700343 Alignment(0), IsConstant(false), ForceSuppressMangling(false) {}
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700344};
345
346template <class StreamType>
347inline StreamType &operator<<(StreamType &Stream,
Karl Schimpf9d98d792014-10-13 15:01:08 -0700348 const VariableDeclaration::Initializer &Init) {
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700349 Init.dump(Stream);
350 return Stream;
351}
352
353template <class StreamType>
Karl Schimpf9d98d792014-10-13 15:01:08 -0700354inline StreamType &operator<<(StreamType &Stream,
355 const GlobalDeclaration &Addr) {
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700356 Addr.dump(Stream);
357 return Stream;
358}
359
360} // end of namespace Ice
361
362#endif // SUBZERO_SRC_ICEGLOBALINITS_H