Add support for global constants, and for initializers for constants
authorChris Lattner <sabre@nondot.org>
Tue, 18 Sep 2001 04:01:05 +0000 (04:01 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 18 Sep 2001 04:01:05 +0000 (04:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@598 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/GlobalVariable.h
lib/Bytecode/Reader/Reader.cpp
lib/Bytecode/Writer/SlotCalculator.cpp
lib/Bytecode/Writer/Writer.cpp
lib/VMCore/AsmWriter.cpp
lib/VMCore/Function.cpp
lib/VMCore/SlotCalculator.cpp

index fd979896182e7fb2f8594996c100b8c24afe84b3..4ee1df9c7258474dbaf576a17c36e0bbbb4301ae 100644 (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
index 71fec255cc56eaf6abe4c4014dffe36972ede589..a2038edf342a5344e6bad1d45939c95e807ac5e0 100644 (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);
 
index cc7d4e56df3e39b1e34896c630e2c23d10a5a712..0ac371cbce7d2e77907a577c03196b3fb5bab350 100644 (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));
   }
 
index e6562f5fb94ffd831417ea4ad8efea7e73b72cfb..da480180a8bcfdf662f4646f2c49db052f4f0828 100644 (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);
 
index 926e61160c99608100cb54742f37f333dbdab75f..f61c54713d385ae749e8102eafef28de4a9a5886 100644 (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;
 }
 
 
index 75a27781a90a7e1d86933fe54283ba3bb204dd2e..47a85395a3f70a91b88479895ea297f99ced83a8 100644 (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
index cc7d4e56df3e39b1e34896c630e2c23d10a5a712..0ac371cbce7d2e77907a577c03196b3fb5bab350 100644 (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));
   }