From ac91b150a74a24930896134e4da7cdbb69644dd1 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 18 Sep 2001 04:01:05 +0000 Subject: [PATCH] Add support for global constants, and for initializers for constants llvm-svn: 598 --- include/llvm/GlobalVariable.h | 40 +++++++++++++++++++++++++++++----- lib/Bytecode/Reader/Reader.cpp | 19 ++++++++++++++-- lib/Bytecode/Writer/Writer.cpp | 16 ++++++++++++-- lib/VMCore/AsmWriter.cpp | 12 ++++++++-- lib/VMCore/Function.cpp | 14 ++++++++---- lib/VMCore/SlotCalculator.cpp | 8 ++++--- 6 files changed, 91 insertions(+), 18 deletions(-) diff --git a/include/llvm/GlobalVariable.h b/include/llvm/GlobalVariable.h index fd979896182..4ee1df9c725 100644 --- a/include/llvm/GlobalVariable.h +++ b/include/llvm/GlobalVariable.h @@ -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; 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 diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp index 71fec255cc5..a2038edf342 100644 --- a/lib/Bytecode/Reader/Reader.cpp +++ b/lib/Bytecode/Reader/Reader.cpp @@ -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); diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp index e6562f5fb94..da480180a8b 100644 --- a/lib/Bytecode/Writer/Writer.cpp +++ b/lib/Bytecode/Writer/Writer.cpp @@ -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); diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 926e61160c9..f61c54713d3 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -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; } diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 75a27781a90..47a85395a3f 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -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 diff --git a/lib/VMCore/SlotCalculator.cpp b/lib/VMCore/SlotCalculator.cpp index cc7d4e56df3..0ac371cbce7 100644 --- a/lib/VMCore/SlotCalculator.cpp +++ b/lib/VMCore/SlotCalculator.cpp @@ -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)); }