blob: e951734faf666ab7f5aaa467f1e7d879938d4267 [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
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the representation of function declarations, global variable
12/// declarations, and the corresponding variable initializers in Subzero.
13///
14/// Global variable initializers are represented as a sequence of simple
15/// initializers.
Andrew Scull9612d322015-07-06 14:53:25 -070016///
Karl Schimpfe3f64d02014-10-07 10:38:22 -070017//===----------------------------------------------------------------------===//
18
19#ifndef SUBZERO_SRC_ICEGLOBALINITS_H
20#define SUBZERO_SRC_ICEGLOBALINITS_H
21
John Porto67f8de92015-06-25 10:14:17 -070022#include "IceDefs.h"
John Portodc619252016-02-10 15:57:16 -080023#include "IceFixups.h"
John Porto67f8de92015-06-25 10:14:17 -070024#include "IceGlobalContext.h"
Karl Schimpfbba77682016-01-15 07:33:15 -080025#include "IceIntrinsics.h"
Jim Stichnoth98ba0062016-03-07 09:26:22 -080026#include "IceMangling.h"
John Porto844211e2016-02-04 08:42:48 -080027#include "IceOperand.h"
John Porto67f8de92015-06-25 10:14:17 -070028#include "IceTypes.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070029
Jim Stichnothb0051df2016-01-13 11:39:15 -080030#ifdef __clang__
Jim Stichnoth98da9662015-06-27 06:38:08 -070031#pragma clang diagnostic push
32#pragma clang diagnostic ignored "-Wunused-parameter"
Jim Stichnothb0051df2016-01-13 11:39:15 -080033#endif // __clang__
34
John Porto1bec8bc2015-06-22 10:51:13 -070035#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" // for NaClBitcodeRecord.
Karl Schimpf9d98d792014-10-13 15:01:08 -070036#include "llvm/IR/CallingConv.h"
John Porto1bec8bc2015-06-22 10:51:13 -070037#include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes.
Jim Stichnothb0051df2016-01-13 11:39:15 -080038
39#ifdef __clang__
Jim Stichnoth98da9662015-06-27 06:38:08 -070040#pragma clang diagnostic pop
Jim Stichnothb0051df2016-01-13 11:39:15 -080041#endif // __clang__
Karl Schimpfe3f64d02014-10-07 10:38:22 -070042
John Porto67f8de92015-06-25 10:14:17 -070043#include <memory>
44#include <utility>
Karl Schimpf9d98d792014-10-13 15:01:08 -070045
46// TODO(kschimpf): Remove ourselves from using LLVM representation for calling
47// conventions and linkage types.
Karl Schimpfe3f64d02014-10-07 10:38:22 -070048
49namespace Ice {
50
Karl Schimpf9d98d792014-10-13 15:01:08 -070051/// Base class for global variable and function declarations.
52class GlobalDeclaration {
Jim Stichnothc6ead202015-02-24 09:30:30 -080053 GlobalDeclaration() = delete;
Karl Schimpf9d98d792014-10-13 15:01:08 -070054 GlobalDeclaration(const GlobalDeclaration &) = delete;
55 GlobalDeclaration &operator=(const GlobalDeclaration &) = delete;
Karl Schimpfe3f64d02014-10-07 10:38:22 -070056
57public:
Karl Schimpf9d98d792014-10-13 15:01:08 -070058 /// Discriminator for LLVM-style RTTI.
59 enum GlobalDeclarationKind {
60 FunctionDeclarationKind,
61 VariableDeclarationKind
62 };
63 GlobalDeclarationKind getKind() const { return Kind; }
Jim Stichnoth467ffe52016-03-29 15:01:06 -070064 GlobalString getName() const { return Name; }
65 void setName(GlobalContext *Ctx, const std::string &NewName) {
66 Name = Ctx->getGlobalString(getSuppressMangling() ? NewName
67 : mangleName(NewName));
Jim Stichnoth98ba0062016-03-07 09:26:22 -080068 }
Jim Stichnoth467ffe52016-03-29 15:01:06 -070069 void setName(GlobalString NewName) { Name = NewName; }
70 void setName(GlobalContext *Ctx) {
71 Name = GlobalString::createWithoutString(Ctx);
72 }
73 bool hasName() const { return Name.hasStdString(); }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070074 bool isInternal() const {
75 return Linkage == llvm::GlobalValue::InternalLinkage;
76 }
77 llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; }
Sean Klein0a3c5232016-03-11 09:49:36 -080078 void setLinkage(llvm::GlobalValue::LinkageTypes L) {
79 assert(!hasName());
80 Linkage = L;
81 }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070082 bool isExternal() const {
83 return Linkage == llvm::GlobalValue::ExternalLinkage;
84 }
Jim Stichnotheafb56c2015-06-22 10:35:22 -070085 virtual ~GlobalDeclaration() = default;
Karl Schimpf9d98d792014-10-13 15:01:08 -070086
Karl Schimpf9d98d792014-10-13 15:01:08 -070087 /// Prints out type of the global declaration.
88 virtual void dumpType(Ostream &Stream) const = 0;
89
90 /// Prints out the global declaration.
Jim Stichnoth98ba0062016-03-07 09:26:22 -080091 virtual void dump(Ostream &Stream) const = 0;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -070092
93 /// Returns true if when emitting names, we should suppress mangling.
94 virtual bool getSuppressMangling() const = 0;
Karl Schimpf9d98d792014-10-13 15:01:08 -070095
Karl Schimpf57d31ac2015-10-07 09:53:12 -070096 /// Returns textual name of linkage.
97 const char *getLinkageName() const {
98 return isInternal() ? "internal" : "external";
99 }
100
Sean Klein0a3c5232016-03-11 09:49:36 -0800101 /// Returns true if the name of this GlobalDeclaration indicates that it
102 /// should have ExternalLinkage (as a special case).
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700103 virtual bool isPNaClABIExternalName(const std::string &Name) const = 0;
Sean Klein0a3c5232016-03-11 09:49:36 -0800104
Karl Schimpf9d98d792014-10-13 15:01:08 -0700105protected:
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700106 GlobalDeclaration(GlobalDeclarationKind Kind,
107 llvm::GlobalValue::LinkageTypes Linkage)
108 : Kind(Kind), Linkage(Linkage) {}
Karl Schimpf9d98d792014-10-13 15:01:08 -0700109
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700110 /// Returns true if linkage is defined correctly for the global declaration,
111 /// based on default rules.
Karl Schimpfd4699942016-04-02 09:55:31 -0700112 bool verifyLinkageDefault() const {
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700113 switch (Linkage) {
114 default:
115 return false;
116 case llvm::GlobalValue::InternalLinkage:
117 return true;
118 case llvm::GlobalValue::ExternalLinkage:
Karl Schimpfd4699942016-04-02 09:55:31 -0700119 return getFlags().getAllowExternDefinedSymbols();
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700120 }
121 }
122
Karl Schimpf9d98d792014-10-13 15:01:08 -0700123 const GlobalDeclarationKind Kind;
Sean Klein0a3c5232016-03-11 09:49:36 -0800124 llvm::GlobalValue::LinkageTypes Linkage;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700125 GlobalString Name;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700126};
127
Andrew Scull57e12682015-09-16 11:30:19 -0700128/// Models a function declaration. This includes the type signature of the
129/// function, its calling conventions, and its linkage.
Karl Schimpf9d98d792014-10-13 15:01:08 -0700130class FunctionDeclaration : public GlobalDeclaration {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800131 FunctionDeclaration() = delete;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700132 FunctionDeclaration(const FunctionDeclaration &) = delete;
133 FunctionDeclaration &operator=(const FunctionDeclaration &) = delete;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700134
135public:
John Porto1bec8bc2015-06-22 10:51:13 -0700136 static FunctionDeclaration *create(GlobalContext *Context,
137 const FuncSigType &Signature,
Karl Schimpf9d98d792014-10-13 15:01:08 -0700138 llvm::CallingConv::ID CallingConv,
139 llvm::GlobalValue::LinkageTypes Linkage,
John Porto1bec8bc2015-06-22 10:51:13 -0700140 bool IsProto) {
141 return new (Context->allocate<FunctionDeclaration>())
142 FunctionDeclaration(Signature, CallingConv, Linkage, IsProto);
143 }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700144 const FuncSigType &getSignature() const { return Signature; }
145 llvm::CallingConv::ID getCallingConv() const { return CallingConv; }
Andrew Scull9612d322015-07-06 14:53:25 -0700146 /// isProto implies that there isn't a (local) definition for the function.
Karl Schimpf9d98d792014-10-13 15:01:08 -0700147 bool isProto() const { return IsProto; }
148 static bool classof(const GlobalDeclaration *Addr) {
149 return Addr->getKind() == FunctionDeclarationKind;
150 }
151 void dumpType(Ostream &Stream) const final;
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800152 void dump(Ostream &Stream) const final;
Jim Stichnothdd842db2015-01-27 12:53:53 -0800153 bool getSuppressMangling() const final { return isExternal() && IsProto; }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700154
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700155 /// Returns true if linkage is correct for the function declaration.
156 bool verifyLinkageCorrect(const GlobalContext *Ctx) const {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700157 if (getName().hasStdString()) {
158 if (isPNaClABIExternalName(getName().toString()) ||
159 isIntrinsicName(Ctx)) {
160 return Linkage == llvm::GlobalValue::ExternalLinkage;
161 }
Sean Klein0a3c5232016-03-11 09:49:36 -0800162 }
Karl Schimpfd4699942016-04-02 09:55:31 -0700163 return verifyLinkageDefault();
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700164 }
165
Karl Schimpfbba77682016-01-15 07:33:15 -0800166 /// Validates that the type signature of the function is correct. Returns true
167 /// if valid.
168 bool validateTypeSignature(const GlobalContext *Ctx) const {
169 bool IsIntrinsic;
170 if (const Intrinsics::FullIntrinsicInfo *Info =
171 getIntrinsicInfo(Ctx, &IsIntrinsic))
172 return validateIntrinsicTypeSignature(Info);
173 return !IsIntrinsic && validateRegularTypeSignature();
174 }
175
176 /// Generates an error message describing why validateTypeSignature returns
177 /// false.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700178 std::string getTypeSignatureError(const GlobalContext *Ctx);
Karl Schimpfbba77682016-01-15 07:33:15 -0800179
180 /// Returns corresponding PNaCl intrisic information.
181 const Intrinsics::FullIntrinsicInfo *
182 getIntrinsicInfo(const GlobalContext *Ctx) const {
183 bool BadIntrinsic;
184 return getIntrinsicInfo(Ctx, &BadIntrinsic);
185 }
186
187 /// Same as above, except IsIntrinsic is true if the function is intrinsic
188 /// (even if not a PNaCl intrinsic).
189 const Intrinsics::FullIntrinsicInfo *
190 getIntrinsicInfo(const GlobalContext *Ctx, bool *IsIntrinsic) const;
191
Karl Schimpf9d98d792014-10-13 15:01:08 -0700192private:
193 const Ice::FuncSigType Signature;
194 llvm::CallingConv::ID CallingConv;
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800195 const bool IsProto;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700196
197 FunctionDeclaration(const FuncSigType &Signature,
198 llvm::CallingConv::ID CallingConv,
199 llvm::GlobalValue::LinkageTypes Linkage, bool IsProto)
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700200 : GlobalDeclaration(FunctionDeclarationKind, Linkage),
201 Signature(Signature), CallingConv(CallingConv), IsProto(IsProto) {}
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700202
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700203 bool isPNaClABIExternalName(const std::string &Name) const override {
Sean Klein0a3c5232016-03-11 09:49:36 -0800204 return Name == "_start";
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700205 }
206
207 bool isIntrinsicName(const GlobalContext *Ctx) const {
Karl Schimpfbba77682016-01-15 07:33:15 -0800208 bool IsIntrinsic;
209 getIntrinsicInfo(Ctx, &IsIntrinsic);
210 return IsIntrinsic;
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700211 }
Karl Schimpfbba77682016-01-15 07:33:15 -0800212
213 bool validateRegularTypeSignature() const;
214
215 bool validateIntrinsicTypeSignature(
216 const Intrinsics::FullIntrinsicInfo *Info) const;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700217};
218
219/// Models a global variable declaration, and its initializers.
220class VariableDeclaration : public GlobalDeclaration {
221 VariableDeclaration(const VariableDeclaration &) = delete;
222 VariableDeclaration &operator=(const VariableDeclaration &) = delete;
Jim Stichnothdd842db2015-01-27 12:53:53 -0800223
Karl Schimpf9d98d792014-10-13 15:01:08 -0700224public:
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700225 /// Base class for a global variable initializer.
226 class Initializer {
227 Initializer(const Initializer &) = delete;
228 Initializer &operator=(const Initializer &) = delete;
229
230 public:
231 /// Discriminator for LLVM-style RTTI.
232 enum InitializerKind {
233 DataInitializerKind,
234 ZeroInitializerKind,
235 RelocInitializerKind
236 };
237 InitializerKind getKind() const { return Kind; }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700238 virtual SizeT getNumBytes() const = 0;
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800239 virtual void dump(Ostream &Stream) const = 0;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700240 virtual void dumpType(Ostream &Stream) const;
241
242 protected:
243 explicit Initializer(InitializerKind Kind) : Kind(Kind) {}
244
245 private:
246 const InitializerKind Kind;
247 };
John Portoa78e4ba2016-03-15 09:28:04 -0700248 static_assert(std::is_trivially_destructible<Initializer>::value,
249 "Initializer must be trivially destructible.");
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700250
Andrew Scull9612d322015-07-06 14:53:25 -0700251 /// Models the data in a data initializer.
John Portoa78e4ba2016-03-15 09:28:04 -0700252 using DataVecType = char *;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700253
254 /// Defines a sequence of byte values as a data initializer.
255 class DataInitializer : public Initializer {
256 DataInitializer(const DataInitializer &) = delete;
257 DataInitializer &operator=(const DataInitializer &) = delete;
258
259 public:
John Porto1bec8bc2015-06-22 10:51:13 -0700260 template <class... Args>
John Portoa78e4ba2016-03-15 09:28:04 -0700261 static DataInitializer *create(VariableDeclarationList *VDL,
262 Args &&... TheArgs) {
263 return new (VDL->allocate_initializer<DataInitializer>())
264 DataInitializer(VDL, std::forward<Args>(TheArgs)...);
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700265 }
John Porto1bec8bc2015-06-22 10:51:13 -0700266
John Portoa78e4ba2016-03-15 09:28:04 -0700267 const llvm::StringRef getContents() const {
268 return llvm::StringRef(Contents, ContentsSize);
269 }
270 SizeT getNumBytes() const final { return ContentsSize; }
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800271 void dump(Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700272 static bool classof(const Initializer *D) {
273 return D->getKind() == DataInitializerKind;
274 }
275
276 private:
John Portoa78e4ba2016-03-15 09:28:04 -0700277 DataInitializer(VariableDeclarationList *VDL,
278 const llvm::NaClBitcodeRecord::RecordVector &Values)
279 : Initializer(DataInitializerKind), ContentsSize(Values.size()),
280 // ugh, we should actually do new char[], but this may involve
281 // implementation-specific details. Given that Contents is arena
Thomas Lively3f5cb6f2016-06-13 11:23:29 -0700282 // allocated, and never delete[]d, just use char --
John Portoa78e4ba2016-03-15 09:28:04 -0700283 // AllocOwner->allocate_array will allocate a buffer with the right
284 // size.
285 Contents(new (VDL->allocate_initializer<char>(ContentsSize)) char) {
John Porto1bec8bc2015-06-22 10:51:13 -0700286 for (SizeT I = 0; I < Values.size(); ++I)
287 Contents[I] = static_cast<int8_t>(Values[I]);
288 }
289
John Portoa78e4ba2016-03-15 09:28:04 -0700290 DataInitializer(VariableDeclarationList *VDL, const char *Str,
291 size_t StrLen)
292 : Initializer(DataInitializerKind), ContentsSize(StrLen),
293 Contents(new (VDL->allocate_initializer<char>(ContentsSize)) char) {
John Porto1bec8bc2015-06-22 10:51:13 -0700294 for (size_t i = 0; i < StrLen; ++i)
295 Contents[i] = Str[i];
296 }
297
Andrew Scull9612d322015-07-06 14:53:25 -0700298 /// The byte contents of the data initializer.
John Portoa78e4ba2016-03-15 09:28:04 -0700299 const SizeT ContentsSize;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700300 DataVecType Contents;
301 };
John Portoa78e4ba2016-03-15 09:28:04 -0700302 static_assert(std::is_trivially_destructible<DataInitializer>::value,
303 "DataInitializer must be trivially destructible.");
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700304
305 /// Defines a sequence of bytes initialized to zero.
306 class ZeroInitializer : public Initializer {
307 ZeroInitializer(const ZeroInitializer &) = delete;
308 ZeroInitializer &operator=(const ZeroInitializer &) = delete;
309
310 public:
John Portoa78e4ba2016-03-15 09:28:04 -0700311 static ZeroInitializer *create(VariableDeclarationList *VDL, SizeT Size) {
312 return new (VDL->allocate_initializer<ZeroInitializer>())
313 ZeroInitializer(Size);
John Porto1bec8bc2015-06-22 10:51:13 -0700314 }
Karl Schimpf9d98d792014-10-13 15:01:08 -0700315 SizeT getNumBytes() const final { return Size; }
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800316 void dump(Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700317 static bool classof(const Initializer *Z) {
318 return Z->getKind() == ZeroInitializerKind;
319 }
320
321 private:
John Porto1bec8bc2015-06-22 10:51:13 -0700322 explicit ZeroInitializer(SizeT Size)
323 : Initializer(ZeroInitializerKind), Size(Size) {}
324
Andrew Scull9612d322015-07-06 14:53:25 -0700325 /// The number of bytes to be zero initialized.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700326 SizeT Size;
327 };
John Portoa78e4ba2016-03-15 09:28:04 -0700328 static_assert(std::is_trivially_destructible<ZeroInitializer>::value,
329 "ZeroInitializer must be trivially destructible.");
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700330
Karl Schimpf9d98d792014-10-13 15:01:08 -0700331 /// Defines the relocation value of another global declaration.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700332 class RelocInitializer : public Initializer {
333 RelocInitializer(const RelocInitializer &) = delete;
334 RelocInitializer &operator=(const RelocInitializer &) = delete;
335
336 public:
John Portoa78e4ba2016-03-15 09:28:04 -0700337 static RelocInitializer *create(VariableDeclarationList *VDL,
338 const GlobalDeclaration *Declaration,
339 const RelocOffsetArray &OffsetExpr) {
John Portodc619252016-02-10 15:57:16 -0800340 constexpr bool NoFixup = false;
John Portoa78e4ba2016-03-15 09:28:04 -0700341 return new (VDL->allocate_initializer<RelocInitializer>())
342 RelocInitializer(VDL, Declaration, OffsetExpr, NoFixup);
John Portodc619252016-02-10 15:57:16 -0800343 }
344
John Portoa78e4ba2016-03-15 09:28:04 -0700345 static RelocInitializer *create(VariableDeclarationList *VDL,
346 const GlobalDeclaration *Declaration,
347 const RelocOffsetArray &OffsetExpr,
348 FixupKind Fixup) {
John Portodc619252016-02-10 15:57:16 -0800349 constexpr bool HasFixup = true;
John Portoa78e4ba2016-03-15 09:28:04 -0700350 return new (VDL->allocate_initializer<RelocInitializer>())
351 RelocInitializer(VDL, Declaration, OffsetExpr, HasFixup, Fixup);
John Porto1bec8bc2015-06-22 10:51:13 -0700352 }
353
John Porto844211e2016-02-04 08:42:48 -0800354 RelocOffsetT getOffset() const {
355 RelocOffsetT Offset = 0;
John Portoa78e4ba2016-03-15 09:28:04 -0700356 for (SizeT i = 0; i < OffsetExprSize; ++i) {
357 Offset += OffsetExpr[i]->getOffset();
John Porto844211e2016-02-04 08:42:48 -0800358 }
359 return Offset;
360 }
361
John Portodc619252016-02-10 15:57:16 -0800362 bool hasFixup() const { return HasFixup; }
363 FixupKind getFixup() const {
364 assert(HasFixup);
365 return Fixup;
366 }
367
Karl Schimpf9d98d792014-10-13 15:01:08 -0700368 const GlobalDeclaration *getDeclaration() const { return Declaration; }
369 SizeT getNumBytes() const final { return RelocAddrSize; }
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800370 void dump(Ostream &Stream) const final;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700371 void dumpType(Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700372 static bool classof(const Initializer *R) {
373 return R->getKind() == RelocInitializerKind;
374 }
375
376 private:
John Portoa78e4ba2016-03-15 09:28:04 -0700377 RelocInitializer(VariableDeclarationList *VDL,
378 const GlobalDeclaration *Declaration,
John Portodc619252016-02-10 15:57:16 -0800379 const RelocOffsetArray &OffsetExpr, bool HasFixup,
380 FixupKind Fixup = 0)
John Porto844211e2016-02-04 08:42:48 -0800381 : Initializer(RelocInitializerKind),
382 Declaration(Declaration), // The global declaration used in the reloc.
John Portoa78e4ba2016-03-15 09:28:04 -0700383 OffsetExprSize(OffsetExpr.size()),
384 OffsetExpr(new (VDL->allocate_initializer<RelocOffset *>(
385 OffsetExprSize)) RelocOffset *),
386 HasFixup(HasFixup), Fixup(Fixup) {
387 for (SizeT i = 0; i < OffsetExprSize; ++i) {
388 this->OffsetExpr[i] = OffsetExpr[i];
389 }
390 }
John Porto1bec8bc2015-06-22 10:51:13 -0700391
Karl Schimpf9d98d792014-10-13 15:01:08 -0700392 const GlobalDeclaration *Declaration;
Andrew Scull9612d322015-07-06 14:53:25 -0700393 /// The offset to add to the relocation.
John Portoa78e4ba2016-03-15 09:28:04 -0700394 const SizeT OffsetExprSize;
395 RelocOffset **OffsetExpr;
John Portodc619252016-02-10 15:57:16 -0800396 const bool HasFixup = false;
397 const FixupKind Fixup = 0;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700398 };
John Portoa78e4ba2016-03-15 09:28:04 -0700399 static_assert(std::is_trivially_destructible<RelocInitializer>::value,
400 "RelocInitializer must be trivially destructible.");
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700401
402 /// Models the list of initializers.
John Portoa78e4ba2016-03-15 09:28:04 -0700403 // TODO(jpp): missing allocator.
404 using InitializerListType = std::vector<Initializer *>;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700405
John Portoa78e4ba2016-03-15 09:28:04 -0700406 static VariableDeclaration *create(VariableDeclarationList *VDL,
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800407 bool SuppressMangling = false,
408 llvm::GlobalValue::LinkageTypes Linkage =
409 llvm::GlobalValue::InternalLinkage) {
John Portoa78e4ba2016-03-15 09:28:04 -0700410 return new (VDL->allocate_variable_declaration<VariableDeclaration>())
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800411 VariableDeclaration(Linkage, SuppressMangling);
412 }
John Portoa78e4ba2016-03-15 09:28:04 -0700413
414 static VariableDeclaration *createExternal(VariableDeclarationList *VDL) {
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800415 constexpr bool SuppressMangling = true;
416 constexpr llvm::GlobalValue::LinkageTypes Linkage =
417 llvm::GlobalValue::ExternalLinkage;
John Portoa78e4ba2016-03-15 09:28:04 -0700418 return create(VDL, SuppressMangling, Linkage);
John Porto1bec8bc2015-06-22 10:51:13 -0700419 }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700420
John Portoa78e4ba2016-03-15 09:28:04 -0700421 const InitializerListType &getInitializers() const { return Initializers; }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700422 bool getIsConstant() const { return IsConstant; }
423 void setIsConstant(bool NewValue) { IsConstant = NewValue; }
424 uint32_t getAlignment() const { return Alignment; }
425 void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; }
John Porto1bec8bc2015-06-22 10:51:13 -0700426 bool hasInitializer() const { return HasInitializer; }
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700427 bool hasNonzeroInitializer() const {
John Portoa78e4ba2016-03-15 09:28:04 -0700428 return !(Initializers.size() == 1 &&
429 llvm::isa<ZeroInitializer>(Initializers[0]));
Karl Schimpf9d98d792014-10-13 15:01:08 -0700430 }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700431
Andrew Scull57e12682015-09-16 11:30:19 -0700432 /// Returns the number of bytes for the initializer of the global address.
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700433 SizeT getNumBytes() const {
434 SizeT Count = 0;
John Portoa78e4ba2016-03-15 09:28:04 -0700435 for (const auto *Init : Initializers) {
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700436 Count += Init->getNumBytes();
437 }
438 return Count;
439 }
440
Andrew Scull57e12682015-09-16 11:30:19 -0700441 /// Adds Initializer to the list of initializers. Takes ownership of the
442 /// initializer.
John Portoa78e4ba2016-03-15 09:28:04 -0700443 void addInitializer(Initializer *Initializer) {
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800444 const bool OldSuppressMangling = getSuppressMangling();
John Portoa78e4ba2016-03-15 09:28:04 -0700445 Initializers.emplace_back(Initializer);
John Porto1bec8bc2015-06-22 10:51:13 -0700446 HasInitializer = true;
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800447 // The getSuppressMangling() logic depends on whether the global variable
448 // has initializers. If its value changed as a result of adding an
449 // initializer, then make sure we haven't previously set the name based on
450 // faulty SuppressMangling logic.
451 const bool SameMangling = (OldSuppressMangling == getSuppressMangling());
452 (void)SameMangling;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700453 assert(Name.hasStdString() || SameMangling);
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700454 }
455
Andrew Scull57e12682015-09-16 11:30:19 -0700456 /// Prints out type for initializer associated with the declaration to Stream.
Karl Schimpf9d98d792014-10-13 15:01:08 -0700457 void dumpType(Ostream &Stream) const final;
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700458
Andrew Scull57e12682015-09-16 11:30:19 -0700459 /// Prints out the definition of the global variable declaration (including
460 /// initialization).
Sean Klein0a3c5232016-03-11 09:49:36 -0800461 virtual void dump(Ostream &Stream) const override;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700462
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700463 /// Returns true if linkage is correct for the variable declaration.
Karl Schimpfd4699942016-04-02 09:55:31 -0700464 bool verifyLinkageCorrect() const {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700465 if (getName().hasStdString()) {
466 if (isPNaClABIExternalName(getName().toString())) {
467 return Linkage == llvm::GlobalValue::ExternalLinkage;
468 }
Sean Klein0a3c5232016-03-11 09:49:36 -0800469 }
Karl Schimpfd4699942016-04-02 09:55:31 -0700470 return verifyLinkageDefault();
Karl Schimpf57d31ac2015-10-07 09:53:12 -0700471 }
472
Karl Schimpf9d98d792014-10-13 15:01:08 -0700473 static bool classof(const GlobalDeclaration *Addr) {
474 return Addr->getKind() == VariableDeclarationKind;
475 }
476
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700477 bool getSuppressMangling() const final {
Jim Stichnothd9f1f9f2015-06-11 10:19:32 -0700478 if (ForceSuppressMangling)
479 return true;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700480 return isExternal() && !hasInitializer();
Karl Schimpf9d98d792014-10-13 15:01:08 -0700481 }
482
John Portoa78e4ba2016-03-15 09:28:04 -0700483 void discardInitializers() { Initializers.clear(); }
John Porto1bec8bc2015-06-22 10:51:13 -0700484
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700485 bool isPNaClABIExternalName(const std::string &Name) const override {
Sean Klein0a3c5232016-03-11 09:49:36 -0800486 return Name == "__pnacl_pso_root";
487 }
488
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700489private:
Andrew Scull9612d322015-07-06 14:53:25 -0700490 /// List of initializers for the declared variable.
John Portoa78e4ba2016-03-15 09:28:04 -0700491 InitializerListType Initializers;
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800492 bool HasInitializer = false;
Andrew Scull9612d322015-07-06 14:53:25 -0700493 /// The alignment of the declared variable.
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800494 uint32_t Alignment = 0;
Andrew Scull9612d322015-07-06 14:53:25 -0700495 /// True if a declared (global) constant.
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800496 bool IsConstant = false;
Andrew Scull9612d322015-07-06 14:53:25 -0700497 /// If set to true, force getSuppressMangling() to return true.
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800498 const bool ForceSuppressMangling;
Karl Schimpf9d98d792014-10-13 15:01:08 -0700499
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800500 VariableDeclaration(llvm::GlobalValue::LinkageTypes Linkage,
501 bool SuppressMangling)
502 : GlobalDeclaration(VariableDeclarationKind, Linkage),
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800503 ForceSuppressMangling(SuppressMangling) {}
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700504};
505
506template <class StreamType>
507inline StreamType &operator<<(StreamType &Stream,
Karl Schimpf9d98d792014-10-13 15:01:08 -0700508 const VariableDeclaration::Initializer &Init) {
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700509 Init.dump(Stream);
510 return Stream;
511}
512
513template <class StreamType>
Karl Schimpf9d98d792014-10-13 15:01:08 -0700514inline StreamType &operator<<(StreamType &Stream,
515 const GlobalDeclaration &Addr) {
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700516 Addr.dump(Stream);
517 return Stream;
518}
519
520} // end of namespace Ice
521
522#endif // SUBZERO_SRC_ICEGLOBALINITS_H