//===-- llvm/Global.h - Class to represent a global variable -----*- C++ -*--=//
//
// This file contains the declaration of the GlobalVariable class, which
-// represents a single global variable in the VM.
+// represents a single global variable (or constant) in the VM.
//
// Global variables are constant pointers that refer to hunks of space that are
-// allocated by either the VM, or by the linker in a static compiler.
+// allocated by either the VM, or by the linker in a static compiler. A global
+// variable may have an intial value, which is copied into the executables .data
+// area. Global Constants are required to have initializers.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_GLOBAL_VARIABLE_H
#define LLVM_GLOBAL_VARIABLE_H
-#include "llvm/Value.h"
+#include "llvm/User.h"
class Module;
+class ConstPoolVal;
+class PointerType;
-class GlobalVariable : public Value {
+class GlobalVariable : public User {
Module *Parent; // The module that contains this method
friend class ValueHolder<GlobalVariable, Module, Module>;
void setParent(Module *parent) { Parent = parent; }
+ bool Constant; // Is this a global constant?
public:
- GlobalVariable(const Type *Ty, const string &Name = "");
+ GlobalVariable(const Type *Ty, bool isConstant, ConstPoolVal *Initializer = 0,
+ const string &Name = "");
~GlobalVariable() {}
+ // getType - Global variables are always pointers
+ inline const PointerType *getType() const {
+ return (const PointerType*)User::getType();
+ }
+
// Specialize setName to handle symbol table majik...
virtual void setName(const string &name, SymbolTable *ST = 0);
inline Module *getParent() { return Parent; }
inline const Module *getParent() const { return Parent; }
+
+ // The initializer for the global variable/constant is held by Operands[0] if
+ // an initializer is specified.
+ //
+ inline bool hasInitializer() const { return !Operands.empty(); }
+ inline const ConstPoolVal *getInitializer() const {
+ return Operands[0]->castConstantAsserting();
+ }
+ inline ConstPoolVal *getInitializer() {
+ return Operands[0]->castConstantAsserting();
+ }
+ inline void setInitializer(ConstPoolVal *CPV) { Operands[0] = (Value*)CPV; }
+
+
+ // If the value is a global constant, its value is immutable throughout the
+ // runtime execution of the program. Assigning a value into the constant
+ // leads to undefined behavior.
+ //
+ inline bool isConstant() const { return Constant; }
};
#endif
unsigned VarType;
if (read_vbr(Buf, End, VarType)) return failure(true);
while (VarType != Type::VoidTyID) { // List is terminated by Void
- const Type *Ty = getType(VarType);
+ // VarType Fields: bit0 = isConstant, bit1 = hasInitializer, bit2+ = slot#
+ const Type *Ty = getType(VarType >> 2);
if (!Ty || !Ty->isPointerType()) {
cerr << "Global not pointer type! Ty = " << Ty << endl;
return failure(true);
}
+ ConstPoolVal *Initializer = 0;
+ if (VarType & 2) { // Does it have an initalizer?
+ // Do not improvise... values must have been stored in the constant pool,
+ // which should have been read before now.
+ //
+ unsigned InitSlot;
+ if (read_vbr(Buf, End, InitSlot)) return failure(true);
+
+ Value *V = getValue(Ty->castPointerType()->getValueType(),
+ InitSlot, false);
+ if (V == 0) return failure(true);
+ Initializer = V->castConstantAsserting();
+ }
+
// Create the global variable...
- GlobalVariable *GV = new GlobalVariable(Ty);
+ GlobalVariable *GV = new GlobalVariable(Ty, VarType & 1, Initializer);
insertValue(GV, ModuleValues);
C->getGlobalList().push_back(GV);
int SlotCalculator::insertValue(const Value *D) {
- if (const ConstPoolVal *CPV = D->castConstant()) {
+ if (D->isConstant() || D->isGlobal()) {
+ const User *U = (const User *)D;
// This makes sure that if a constant has uses (for example an array
- // of const ints), that they are inserted also.
+ // of const ints), that they are inserted also. Same for global variable
+ // initializers.
//
- for_each(CPV->op_begin(), CPV->op_end(),
+ for_each(U->op_begin(), U->op_end(),
bind_obj(this, &SlotCalculator::insertValue));
}
// Output the types for the global variables in the module...
for (Module::const_giterator I = M->gbegin(), End = M->gend(); I != End;++I) {
- int Slot = Table.getValSlot((*I)->getType());
+ const GlobalVariable *GV = *I;
+ int Slot = Table.getValSlot(GV->getType());
assert(Slot != -1 && "Module global vars is broken!");
- output_vbr((unsigned)Slot, Out);
+
+ // Fields: bit0 = isConstant, bit1 = hasInitializer, bit2+ = slot#
+ unsigned oSlot = ((unsigned)Slot << 2) | (GV->hasInitializer() << 1) |
+ GV->isConstant();
+ output_vbr(oSlot, Out);
+
+ // If we have an initialized, output it now.
+ if (GV->hasInitializer()) {
+ Slot = Table.getValSlot(GV->getInitializer());
+ assert(Slot != -1 && "No slot for global var initializer!");
+ output_vbr((unsigned)Slot, Out);
+ }
}
output_vbr((unsigned)Table.getValSlot(Type::VoidTy), Out);
}
void AssemblyWriter::processGlobal(const GlobalVariable *GV) {
- Out << "global ";
if (GV->hasName()) Out << "%" << GV->getName() << " = ";
- Out << GV->getType()->getDescription() << endl;
+
+ if (!GV->hasInitializer()) Out << "uninitialized ";
+
+ Out << (GV->isConstant() ? "constant " : "global ")
+ << GV->getType()->getValueType()->getDescription();
+
+ if (GV->hasInitializer())
+ writeOperand(GV->getInitializer(), false, false);
+
+ Out << endl;
}
// GlobalVariable Implementation
//===----------------------------------------------------------------------===//
-GlobalVariable::GlobalVariable(const Type *Ty, const string &Name = "")
- : Value(Ty, Value::GlobalVal, Name), Parent(0) {
+GlobalVariable::GlobalVariable(const Type *Ty, bool isConstant,
+ ConstPoolVal *Initializer = 0,
+ const string &Name = "")
+ : User(Ty, Value::GlobalVal, Name), Parent(0), Constant(isConstant) {
assert(Ty->isPointerType() && // No unsized array pointers
- (!Ty->dyncastPointerType()->isArrayType() ||
- Ty->dyncastPointerType()->dyncastArrayType()->isSized()) &&
+ (!Ty->castPointerType()->isArrayType() ||
+ Ty->castPointerType()->castArrayType()->isSized()) &&
"Global Variables must be pointers to a sized type!");
+ if (Initializer) Operands.push_back(Use((Value*)Initializer, this));
+
+ assert(!isConstant || hasInitializer() &&
+ "Globals Constants must have an initializer!");
}
// Specialize setName to take care of symbol table majik
int SlotCalculator::insertValue(const Value *D) {
- if (const ConstPoolVal *CPV = D->castConstant()) {
+ if (D->isConstant() || D->isGlobal()) {
+ const User *U = (const User *)D;
// This makes sure that if a constant has uses (for example an array
- // of const ints), that they are inserted also.
+ // of const ints), that they are inserted also. Same for global variable
+ // initializers.
//
- for_each(CPV->op_begin(), CPV->op_end(),
+ for_each(U->op_begin(), U->op_end(),
bind_obj(this, &SlotCalculator::insertValue));
}