Add support for global constants, and for initializers for constants

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@598 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2001-09-18 04:01:05 +00:00
parent 1781acab34
commit d70684f758
7 changed files with 96 additions and 21 deletions

View File

@ -1,34 +1,64 @@
//===-- llvm/Global.h - Class to represent a global variable -----*- C++ -*--=// //===-- llvm/Global.h - Class to represent a global variable -----*- C++ -*--=//
// //
// This file contains the declaration of the GlobalVariable class, which // 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 // 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 #ifndef LLVM_GLOBAL_VARIABLE_H
#define LLVM_GLOBAL_VARIABLE_H #define LLVM_GLOBAL_VARIABLE_H
#include "llvm/Value.h" #include "llvm/User.h"
class Module; class Module;
class ConstPoolVal;
class PointerType;
class GlobalVariable : public Value { class GlobalVariable : public User {
Module *Parent; // The module that contains this method Module *Parent; // The module that contains this method
friend class ValueHolder<GlobalVariable, Module, Module>; friend class ValueHolder<GlobalVariable, Module, Module>;
void setParent(Module *parent) { Parent = parent; } void setParent(Module *parent) { Parent = parent; }
bool Constant; // Is this a global constant?
public: public:
GlobalVariable(const Type *Ty, const string &Name = ""); GlobalVariable(const Type *Ty, bool isConstant, ConstPoolVal *Initializer = 0,
const string &Name = "");
~GlobalVariable() {} ~GlobalVariable() {}
// getType - Global variables are always pointers
inline const PointerType *getType() const {
return (const PointerType*)User::getType();
}
// Specialize setName to handle symbol table majik... // Specialize setName to handle symbol table majik...
virtual void setName(const string &name, SymbolTable *ST = 0); virtual void setName(const string &name, SymbolTable *ST = 0);
inline Module *getParent() { return Parent; } inline Module *getParent() { return Parent; }
inline const Module *getParent() const { 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 #endif

View File

@ -323,14 +323,29 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
unsigned VarType; unsigned VarType;
if (read_vbr(Buf, End, VarType)) return failure(true); if (read_vbr(Buf, End, VarType)) return failure(true);
while (VarType != Type::VoidTyID) { // List is terminated by Void 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()) { if (!Ty || !Ty->isPointerType()) {
cerr << "Global not pointer type! Ty = " << Ty << endl; cerr << "Global not pointer type! Ty = " << Ty << endl;
return failure(true); 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... // Create the global variable...
GlobalVariable *GV = new GlobalVariable(Ty); GlobalVariable *GV = new GlobalVariable(Ty, VarType & 1, Initializer);
insertValue(GV, ModuleValues); insertValue(GV, ModuleValues);
C->getGlobalList().push_back(GV); C->getGlobalList().push_back(GV);

View File

@ -223,11 +223,13 @@ int SlotCalculator::getValSlot(const Value *D) const {
int SlotCalculator::insertValue(const Value *D) { 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 // 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)); bind_obj(this, &SlotCalculator::insertValue));
} }

View File

@ -120,9 +120,21 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
// Output the types for the global variables in the module... // Output the types for the global variables in the module...
for (Module::const_giterator I = M->gbegin(), End = M->gend(); I != End;++I) { 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!"); 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); output_vbr((unsigned)Table.getValSlot(Type::VoidTy), Out);

View File

@ -123,9 +123,17 @@ void AssemblyWriter::processModule(const Module *M) {
} }
void AssemblyWriter::processGlobal(const GlobalVariable *GV) { void AssemblyWriter::processGlobal(const GlobalVariable *GV) {
Out << "global ";
if (GV->hasName()) Out << "%" << GV->getName() << " = "; 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;
} }

View File

@ -82,12 +82,18 @@ void Method::dropAllReferences() {
// GlobalVariable Implementation // GlobalVariable Implementation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
GlobalVariable::GlobalVariable(const Type *Ty, const string &Name = "") GlobalVariable::GlobalVariable(const Type *Ty, bool isConstant,
: Value(Ty, Value::GlobalVal, Name), Parent(0) { ConstPoolVal *Initializer = 0,
const string &Name = "")
: User(Ty, Value::GlobalVal, Name), Parent(0), Constant(isConstant) {
assert(Ty->isPointerType() && // No unsized array pointers assert(Ty->isPointerType() && // No unsized array pointers
(!Ty->dyncastPointerType()->isArrayType() || (!Ty->castPointerType()->isArrayType() ||
Ty->dyncastPointerType()->dyncastArrayType()->isSized()) && Ty->castPointerType()->castArrayType()->isSized()) &&
"Global Variables must be pointers to a sized type!"); "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 // Specialize setName to take care of symbol table majik

View File

@ -223,11 +223,13 @@ int SlotCalculator::getValSlot(const Value *D) const {
int SlotCalculator::insertValue(const Value *D) { 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 // 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)); bind_obj(this, &SlotCalculator::insertValue));
} }