Index: src/IceGlobalInits.h |
diff --git a/src/IceGlobalInits.h b/src/IceGlobalInits.h |
index 09e5574a0b01139f94f2f4cda63aadda10612c86..0f6565c03f01862dfc0f2571ae6dab433314a767 100644 |
--- a/src/IceGlobalInits.h |
+++ b/src/IceGlobalInits.h |
@@ -1,4 +1,4 @@ |
-//===- subzero/src/IceGlobalInits.h - Global initializers -------*- C++ -*-===// |
+//===- subzero/src/IceGlobalInits.h - Global declarations -------*- C++ -*-===// |
// |
// The Subzero Code Generator |
// |
@@ -7,29 +7,117 @@ |
// |
//===----------------------------------------------------------------------===// |
// |
-// This file declares the representation of global addresses and |
-// initializers in Subzero. Global initializers are represented as a |
-// sequence of simple initializers. |
+// This file declares the representation of function declarations, |
+// global variable declarations, and the corresponding variable |
+// initializers in Subzero. Global variable initializers are |
+// represented as a sequence of simple initializers. |
// |
//===----------------------------------------------------------------------===// |
#ifndef SUBZERO_SRC_ICEGLOBALINITS_H |
#define SUBZERO_SRC_ICEGLOBALINITS_H |
+#include "llvm/IR/CallingConv.h" |
+#include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes |
+ |
#include "IceDefs.h" |
+#include "IceTypes.h" |
-namespace llvm { |
-// TODO(kschimpf): Remove this dependency on LLVM IR. |
-class Value; |
-} |
+// TODO(kschimpf): Remove ourselves from using LLVM representation for calling |
+// conventions and linkage types. |
namespace Ice { |
-/// Models a global address, and its initializers. |
-class GlobalAddress { |
- GlobalAddress(const GlobalAddress &) = delete; |
- GlobalAddress &operator=(const GlobalAddress &) = delete; |
+/// Base class for global variable and function declarations. |
+class GlobalDeclaration { |
+ GlobalDeclaration(const GlobalDeclaration &) = delete; |
+ GlobalDeclaration &operator=(const GlobalDeclaration &) = delete; |
+ |
+public: |
+ /// Discriminator for LLVM-style RTTI. |
+ enum GlobalDeclarationKind { |
+ FunctionDeclarationKind, |
+ VariableDeclarationKind |
+ }; |
+ GlobalDeclarationKind getKind() const { return Kind; } |
+ const IceString &getName() const { return Name; } |
+ void setName(const IceString &NewName) { Name = NewName; } |
+ bool hasName() const { return !Name.empty(); } |
+ virtual ~GlobalDeclaration() {} |
+ |
+ /// Returns true if the declaration is external. |
+ virtual bool getIsExternal() const = 0; |
+ |
+ /// Prints out type of the global declaration. |
+ virtual void dumpType(Ostream &Stream) const = 0; |
+ |
+ /// Prints out the global declaration. |
+ virtual void dump(Ostream &Stream) const = 0; |
+ |
+ // Mangles name for cross tests, unless external and not defined locally |
+ // (so that relocations accross llvm2ice and pnacl-llc will work). |
+ virtual IceString mangleName(GlobalContext *Ctx) const = 0; |
+ |
+protected: |
+ GlobalDeclaration(GlobalDeclarationKind Kind) : Kind(Kind) {} |
+ |
+ const GlobalDeclarationKind Kind; |
+ IceString Name; |
+}; |
+ |
+// Models a function declaration. This includes the type signature of |
+// the function, its calling conventions, and its linkage. |
+class FunctionDeclaration : public GlobalDeclaration { |
+ FunctionDeclaration(const FunctionDeclaration &) = delete; |
+ FunctionDeclaration &operator=(const FunctionDeclaration &) = delete; |
+ friend class GlobalContext; |
+ |
+public: |
+ static FunctionDeclaration *create(GlobalContext *Ctx, |
+ const FuncSigType &Signature, |
+ llvm::CallingConv::ID CallingConv, |
+ llvm::GlobalValue::LinkageTypes Linkage, |
+ bool IsProto); |
+ ~FunctionDeclaration() final {} |
+ const FuncSigType &getSignature() const { return Signature; } |
+ llvm::CallingConv::ID getCallingConv() const { return CallingConv; } |
+ llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; } |
+ // isProto implies that there isn't a (local) definition for the function. |
+ bool isProto() const { return IsProto; } |
+ static bool classof(const GlobalDeclaration *Addr) { |
+ return Addr->getKind() == FunctionDeclarationKind; |
+ } |
+ void dumpType(Ostream &Stream) const final; |
+ void dump(Ostream &Stream) const final; |
+ bool getIsExternal() const final { |
+ return Linkage == llvm::GlobalValue::ExternalLinkage; |
+ } |
+ |
+ virtual IceString mangleName(GlobalContext *Ctx) const final { |
+ return (getIsExternal() && IsProto) ? Name : Ctx->mangleName(Name); |
+ } |
+ |
+private: |
+ const Ice::FuncSigType Signature; |
+ llvm::CallingConv::ID CallingConv; |
+ llvm::GlobalValue::LinkageTypes Linkage; |
+ bool IsProto; |
+ |
+ FunctionDeclaration(const FuncSigType &Signature, |
+ llvm::CallingConv::ID CallingConv, |
+ llvm::GlobalValue::LinkageTypes Linkage, bool IsProto) |
+ : GlobalDeclaration(FunctionDeclarationKind), Signature(Signature), |
+ CallingConv(CallingConv), Linkage(Linkage), IsProto(IsProto) {} |
+}; |
+/// Models a global variable declaration, and its initializers. |
+class VariableDeclaration : public GlobalDeclaration { |
+ VariableDeclaration(const VariableDeclaration &) = delete; |
+ VariableDeclaration &operator=(const VariableDeclaration &) = delete; |
+ friend class GlobalContext; |
+ // TODO(kschimpf) Factor out allocation of initializers into the |
+ // global context, so that memory allocation/collection can be |
+ // optimized. |
public: |
/// Base class for a global variable initializer. |
class Initializer { |
@@ -81,8 +169,8 @@ public: |
} |
~DataInitializer() override {} |
const DataVecType &getContents() const { return Contents; } |
- SizeT getNumBytes() const override { return Contents.size(); } |
- void dump(Ostream &Stream) const override; |
+ SizeT getNumBytes() const final { return Contents.size(); } |
+ void dump(Ostream &Stream) const final; |
static bool classof(const Initializer *D) { |
return D->getKind() == DataInitializerKind; |
} |
@@ -101,8 +189,8 @@ public: |
explicit ZeroInitializer(SizeT Size) |
: Initializer(ZeroInitializerKind), Size(Size) {} |
~ZeroInitializer() override {} |
- SizeT getNumBytes() const override { return Size; } |
- void dump(Ostream &Stream) const override; |
+ SizeT getNumBytes() const final { return Size; } |
+ void dump(Ostream &Stream) const final; |
static bool classof(const Initializer *Z) { |
return Z->getKind() == ZeroInitializerKind; |
} |
@@ -112,76 +200,33 @@ public: |
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. |
+ /// Defines the relocation value of another global declaration. |
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(const GlobalDeclaration *Declaration, |
+ RelocOffsetType Offset) |
+ : Initializer(RelocInitializerKind), Declaration(Declaration), |
+ 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; |
+ const GlobalDeclaration *getDeclaration() const { return Declaration; } |
+ SizeT getNumBytes() const final { return RelocAddrSize; } |
+ void dump(Ostream &Stream) const final; |
+ void dumpType(Ostream &Stream) const final; |
static bool classof(const Initializer *R) { |
return R->getKind() == RelocInitializerKind; |
} |
private: |
- // The global address used in the relocation. |
- const RelocationAddress Address; |
+ // The global declaration used in the relocation. |
+ const GlobalDeclaration *Declaration; |
// The offset to add to the relocation. |
const RelocOffsetType Offset; |
}; |
@@ -189,19 +234,21 @@ public: |
/// Models the list of initializers. |
typedef std::vector<Initializer *> InitializerListType; |
- GlobalAddress() : Alignment(0), IsConstant(false), IsInternal(true) {} |
- ~GlobalAddress(); |
+ static VariableDeclaration *create(GlobalContext *Ctx); |
+ ~VariableDeclaration() final; |
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; } |
+ bool getIsExternal() const final { return !getIsInternal(); } |
+ bool hasInitializer() const { |
+ return !(Initializers.size() == 1 && |
+ llvm::isa<ZeroInitializer>(Initializers[0])); |
+ } |
/// Returns the number of bytes for the initializer of the global |
/// address. |
@@ -219,36 +266,49 @@ public: |
Initializers.push_back(Initializer); |
} |
- /// Prints out type for initializer associated with the global address |
+ /// Prints out type for initializer associated with the declaration |
/// to Stream. |
- void dumpType(Ostream &Stream) const; |
+ void dumpType(Ostream &Stream) const final; |
+ |
+ /// Prints out the definition of the global variable declaration |
+ /// (including initialization). |
+ void dump(Ostream &Stream) const final; |
+ |
+ static bool classof(const GlobalDeclaration *Addr) { |
+ return Addr->getKind() == VariableDeclarationKind; |
+ } |
+ |
+ IceString mangleName(GlobalContext *Ctx) const final { |
+ return (getIsExternal() && !hasInitializer()) |
+ ? Name : Ctx->mangleName(Name); |
+ } |
- /// Prints out the definition of the global address (including |
- /// initialization). |
- void dump(Ostream &Stream) const; |
private: |
- // list of initializers associated with the global address. |
+ // list of initializers for the declared variable. |
InitializerListType Initializers; |
- // The name for the global. |
- IceString Name; |
- // The alignment of the initializer. |
+ // The alignment of the declared variable. |
uint32_t Alignment; |
- // True if a constant initializer. |
+ // True if a declared (global) constant. |
bool IsConstant; |
- // True if the address is internal. |
+ // True if the declaration is internal. |
bool IsInternal; |
+ |
+ VariableDeclaration() |
+ : GlobalDeclaration(VariableDeclarationKind), Alignment(0), |
+ IsConstant(false), IsInternal(true) {} |
}; |
template <class StreamType> |
inline StreamType &operator<<(StreamType &Stream, |
- const GlobalAddress::Initializer &Init) { |
+ const VariableDeclaration::Initializer &Init) { |
Init.dump(Stream); |
return Stream; |
} |
template <class StreamType> |
-inline StreamType &operator<<(StreamType &Stream, const GlobalAddress &Addr) { |
+inline StreamType &operator<<(StreamType &Stream, |
+ const GlobalDeclaration &Addr) { |
Addr.dump(Stream); |
return Stream; |
} |