blob: 09e5574a0b01139f94f2f4cda63aadda10612c86 [file] [log] [blame]
//===- subzero/src/IceGlobalInits.h - Global initializers -------*- C++ -*-===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the representation of global addresses and
// initializers in Subzero. Global initializers are represented as a
// sequence of simple initializers.
//
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEGLOBALINITS_H
#define SUBZERO_SRC_ICEGLOBALINITS_H
#include "IceDefs.h"
namespace llvm {
// TODO(kschimpf): Remove this dependency on LLVM IR.
class Value;
}
namespace Ice {
/// Models a global address, and its initializers.
class GlobalAddress {
GlobalAddress(const GlobalAddress &) = delete;
GlobalAddress &operator=(const GlobalAddress &) = delete;
public:
/// Base class for a global variable initializer.
class Initializer {
Initializer(const Initializer &) = delete;
Initializer &operator=(const Initializer &) = delete;
public:
/// Discriminator for LLVM-style RTTI.
enum InitializerKind {
DataInitializerKind,
ZeroInitializerKind,
RelocInitializerKind
};
InitializerKind getKind() const { return Kind; }
virtual ~Initializer() {}
virtual SizeT getNumBytes() const = 0;
virtual void dump(Ostream &Stream) const = 0;
virtual void dumpType(Ostream &Stream) const;
protected:
explicit Initializer(InitializerKind Kind) : Kind(Kind) {}
private:
const InitializerKind Kind;
};
// Models the data in a data initializer.
typedef std::vector<uint8_t> DataVecType;
/// Defines a sequence of byte values as a data initializer.
class DataInitializer : public Initializer {
DataInitializer(const DataInitializer &) = delete;
DataInitializer &operator=(const DataInitializer &) = delete;
public:
template <class IntContainer>
DataInitializer(const IntContainer &Values)
: Initializer(DataInitializerKind), Contents(Values.size()) {
size_t i = 0;
for (auto &V : Values) {
Contents[i] = static_cast<uint8_t>(V);
++i;
}
}
DataInitializer(const char *Str, size_t StrLen)
: Initializer(DataInitializerKind), Contents(StrLen) {
for (size_t i = 0; i < StrLen; ++i)
Contents[i] = static_cast<uint8_t>(Str[i]);
}
~DataInitializer() override {}
const DataVecType &getContents() const { return Contents; }
SizeT getNumBytes() const override { return Contents.size(); }
void dump(Ostream &Stream) const override;
static bool classof(const Initializer *D) {
return D->getKind() == DataInitializerKind;
}
private:
// The byte contents of the data initializer.
DataVecType Contents;
};
/// Defines a sequence of bytes initialized to zero.
class ZeroInitializer : public Initializer {
ZeroInitializer(const ZeroInitializer &) = delete;
ZeroInitializer &operator=(const ZeroInitializer &) = delete;
public:
explicit ZeroInitializer(SizeT Size)
: Initializer(ZeroInitializerKind), Size(Size) {}
~ZeroInitializer() override {}
SizeT getNumBytes() const override { return Size; }
void dump(Ostream &Stream) const override;
static bool classof(const Initializer *Z) {
return Z->getKind() == ZeroInitializerKind;
}
private:
// The number of bytes to be zero initialized.
SizeT Size;
};
/// Defines the kind of relocation addresses allowed.
enum RelocationKind { FunctionRelocation, GlobalAddressRelocation };
/// Defines a relocation address (i.e. reference to a function
/// or global variable address).
class RelocationAddress {
RelocationAddress &operator=(const RelocationAddress &) = delete;
public:
explicit RelocationAddress(const RelocationAddress &Addr)
: Kind(Addr.Kind) {
switch (Kind) {
case FunctionRelocation:
Address.Function = Addr.Address.Function;
break;
case GlobalAddressRelocation:
Address.GlobalAddr = Addr.Address.GlobalAddr;
}
}
explicit RelocationAddress(llvm::Value *Function)
: Kind(FunctionRelocation) {
Address.Function = Function;
}
explicit RelocationAddress(GlobalAddress *GlobalAddr)
: Kind(GlobalAddressRelocation) {
Address.GlobalAddr = GlobalAddr;
}
RelocationKind getKind() const { return Kind; }
llvm::Value *getFunction() const {
assert(Kind == FunctionRelocation);
return Address.Function;
}
GlobalAddress *getGlobalAddr() const {
assert(Kind == GlobalAddressRelocation);
return Address.GlobalAddr;
}
private:
const RelocationKind Kind;
union {
// TODO(kschimpf) Integrate Functions into ICE model.
llvm::Value *Function;
GlobalAddress *GlobalAddr;
} Address;
};
// Relocation address offsets must be 32 bit values.
typedef int32_t RelocOffsetType;
static const SizeT RelocAddrSize = 4;
/// Defines the relocation value of another address.
class RelocInitializer : public Initializer {
RelocInitializer(const RelocInitializer &) = delete;
RelocInitializer &operator=(const RelocInitializer &) = delete;
public:
RelocInitializer(const RelocationAddress &Address, RelocOffsetType Offset)
: Initializer(RelocInitializerKind), Address(Address), Offset(Offset) {}
~RelocInitializer() override {}
RelocOffsetType getOffset() const { return Offset; }
IceString getName() const;
SizeT getNumBytes() const override { return RelocAddrSize; }
void dump(Ostream &Stream) const override;
virtual void dumpType(Ostream &Stream) const;
static bool classof(const Initializer *R) {
return R->getKind() == RelocInitializerKind;
}
private:
// The global address used in the relocation.
const RelocationAddress Address;
// The offset to add to the relocation.
const RelocOffsetType Offset;
};
/// Models the list of initializers.
typedef std::vector<Initializer *> InitializerListType;
GlobalAddress() : Alignment(0), IsConstant(false), IsInternal(true) {}
~GlobalAddress();
const InitializerListType &getInitializers() const { return Initializers; }
bool hasName() const { return !Name.empty(); }
const IceString &getName() const { return Name; }
void setName(const IceString &NewName) { Name = NewName; }
bool getIsConstant() const { return IsConstant; }
void setIsConstant(bool NewValue) { IsConstant = NewValue; }
uint32_t getAlignment() const { return Alignment; }
void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; }
bool getIsInternal() const { return IsInternal; }
void setIsInternal(bool NewValue) { IsInternal = NewValue; }
/// Returns the number of bytes for the initializer of the global
/// address.
SizeT getNumBytes() const {
SizeT Count = 0;
for (Initializer *Init : Initializers) {
Count += Init->getNumBytes();
}
return Count;
}
/// Adds Initializer to the list of initializers. Takes ownership of
/// the initializer.
void addInitializer(Initializer *Initializer) {
Initializers.push_back(Initializer);
}
/// Prints out type for initializer associated with the global address
/// to Stream.
void dumpType(Ostream &Stream) const;
/// Prints out the definition of the global address (including
/// initialization).
void dump(Ostream &Stream) const;
private:
// list of initializers associated with the global address.
InitializerListType Initializers;
// The name for the global.
IceString Name;
// The alignment of the initializer.
uint32_t Alignment;
// True if a constant initializer.
bool IsConstant;
// True if the address is internal.
bool IsInternal;
};
template <class StreamType>
inline StreamType &operator<<(StreamType &Stream,
const GlobalAddress::Initializer &Init) {
Init.dump(Stream);
return Stream;
}
template <class StreamType>
inline StreamType &operator<<(StreamType &Stream, const GlobalAddress &Addr) {
Addr.dump(Stream);
return Stream;
}
} // end of namespace Ice
#endif // SUBZERO_SRC_ICEGLOBALINITS_H