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++ -*--=//
//
// 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

View File

@ -323,14 +323,29 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
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);

View File

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

View File

@ -120,9 +120,21 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
// 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);

View File

@ -123,9 +123,17 @@ void AssemblyWriter::processModule(const Module *M) {
}
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;
}

View File

@ -82,12 +82,18 @@ void Method::dropAllReferences() {
// 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

View File

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