Implement global variable support


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@530 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l
index 9c3f947..6a650a3 100644
--- a/lib/AsmParser/Lexer.l
+++ b/lib/AsmParser/Lexer.l
@@ -122,6 +122,7 @@
 true            { return TRUE;  }
 false           { return FALSE; }
 declare         { return DECLARE; }
+global          { return GLOBAL; }
 implementation  { return IMPLEMENTATION; }
 \.\.\.          { return DOTDOTDOT; }
 string          { return STRING; }
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index 9971050..0568b33 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -12,13 +12,13 @@
 
 %{
 #include "ParserInternals.h"
-#include "llvm/BasicBlock.h"
-#include "llvm/Method.h"
+#include "llvm/Assembly/Parser.h"
 #include "llvm/SymbolTable.h"
 #include "llvm/Module.h"
-#include "llvm/Type.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Method.h"
+#include "llvm/BasicBlock.h"
 #include "llvm/DerivedTypes.h"
-#include "llvm/Assembly/Parser.h"
 #include "llvm/iTerminators.h"
 #include "llvm/iMemory.h"
 #include "llvm/CFG.h"         // TODO: Change this when we have a DF.h
@@ -568,7 +568,7 @@
 %type  <StrVal>  OptVAR_ID OptAssign
 
 
-%token IMPLEMENTATION TRUE FALSE BEGINTOK END DECLARE TO DOTDOTDOT STRING
+%token IMPLEMENTATION TRUE FALSE BEGINTOK END DECLARE GLOBAL TO DOTDOTDOT STRING
 
 // Basic Block Terminating Operators 
 %token <TermOpVal> RET BR SWITCH
@@ -871,15 +871,23 @@
   }
   | ConstPool MethodProto {            // Method prototypes can be in const pool
   }
-/*
-  | ConstPool OptAssign GlobalDecl {     // Global declarations appear in CP
-    if ($2) {
-      setValueName($3, $2);
-      free($2);
+  | ConstPool GLOBAL OptAssign Types { // Global declarations appear in CP
+    if (!$4->get()->isPointerType() || 
+	(((PointerType*)$4->get())->isArrayType() && 
+	 ((PointerType*)$4->get())->isArrayType()->isUnsized())) {
+      ThrowException("Type '" + $4->get()->getDescription() +
+		     "' is not a pointer to a sized type!");
     }
-    //CurModule.CurrentModule->
+
+    GlobalVariable *GV = new GlobalVariable(*$4);
+    delete $4;
+    if ($3) {
+      setValueName(GV, $3);
+      free($3);
+    }
+    CurModule.CurrentModule->getGlobalList().push_back(GV);
+    InsertValue(GV, CurModule.Values);
   }
-*/
   | /* empty: end of list */ { 
   }
 
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp
index 5407683..eab576e 100644
--- a/lib/Bytecode/Reader/Reader.cpp
+++ b/lib/Bytecode/Reader/Reader.cpp
@@ -12,6 +12,7 @@
 
 #include "llvm/Bytecode/Reader.h"
 #include "llvm/Bytecode/Format.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/Module.h"
 #include "llvm/BasicBlock.h"
 #include "llvm/DerivedTypes.h"
@@ -312,10 +313,28 @@
 
 bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
 					  Module *C) {
-
   if (!MethodSignatureList.empty()) 
     return failure(true);  // Two ModuleGlobal blocks?
 
+  // Read global variables...
+  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);
+    if (!Ty || !Ty->isPointerType()) { 
+      cerr << "Global not pointer type!  Ty = " << Ty << endl;
+      return failure(true); 
+    }
+
+    // Create the global variable...
+    GlobalVariable *GV = new GlobalVariable(Ty);
+    insertValue(GV, ModuleValues);
+    C->getGlobalList().push_back(GV);
+
+    if (read_vbr(Buf, End, VarType)) return failure(true);
+    BCR_TRACE(2, "Global Variable of type: " << Ty->getDescription() << endl);
+  }
+
   // Read the method signatures for all of the methods that are coming, and 
   // create fillers in the Value tables.
   unsigned MethSignature;
@@ -324,7 +343,6 @@
     const Type *Ty = getType(MethSignature);
     if (!Ty || !Ty->isMethodType()) { 
       cerr << "Method not meth type!  Ty = " << Ty << endl;
-      if (Ty) cerr << Ty->getName(); else cerr << MethSignature; cerr << endl; 
       return failure(true); 
     }
 
diff --git a/lib/Bytecode/Writer/SlotCalculator.cpp b/lib/Bytecode/Writer/SlotCalculator.cpp
index 9af5a38..cc7d4e5 100644
--- a/lib/Bytecode/Writer/SlotCalculator.cpp
+++ b/lib/Bytecode/Writer/SlotCalculator.cpp
@@ -12,6 +12,7 @@
 #include "llvm/Analysis/SlotCalculator.h"
 #include "llvm/Analysis/ConstantsScanner.h"
 #include "llvm/Method.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/Module.h"
 #include "llvm/BasicBlock.h"
 #include "llvm/ConstPoolVals.h"
@@ -68,13 +69,21 @@
 //
 void SlotCalculator::processModule() {
   SC_DEBUG("begin processModule!\n");
-  // Currently, the only module level declarations are methods and method
-  // prototypes.  We simply scavenge the types out of the methods, then add the
-  // methods themselves to the value table...
+
+  // Add all of the global variables to the value table...
+  //
+  for_each(TheModule->gbegin(), TheModule->gend(),
+	   bind_obj(this, &SlotCalculator::insertValue));
+
+  // Scavenge the types out of the methods, then add the methods themselves to
+  // the value table...
   //
   for_each(TheModule->begin(), TheModule->end(),  // Insert methods...
 	   bind_obj(this, &SlotCalculator::insertValue));
 
+  // Insert constants that are named at module level into the slot pool so that
+  // the module symbol table can refer to them...
+  //
   if (TheModule->hasSymbolTable() && !IgnoreNamedNodes) {
     SC_DEBUG("Inserting SymbolTable values:\n");
     processSymbolTable(TheModule->getSymbolTable());
diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp
index 4235145..e6562f5 100644
--- a/lib/Bytecode/Writer/Writer.cpp
+++ b/lib/Bytecode/Writer/Writer.cpp
@@ -24,6 +24,7 @@
 
 #include "WriterInternals.h"
 #include "llvm/Module.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/Method.h"
 #include "llvm/BasicBlock.h"
 #include "llvm/ConstPoolVals.h"
@@ -117,7 +118,15 @@
 void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
   BytecodeBlock ModuleInfoBlock(BytecodeFormat::ModuleGlobalInfo, Out);
   
-  // Output the types of the methods in this class
+  // 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());
+    assert(Slot != -1 && "Module global vars is broken!");
+    output_vbr((unsigned)Slot, Out);
+  }
+  output_vbr((unsigned)Table.getValSlot(Type::VoidTy), Out);
+
+  // Output the types of the methods in this module...
   for (Module::const_iterator I = M->begin(), End = M->end(); I != End; ++I) {
     int Slot = Table.getValSlot((*I)->getType());
     assert(Slot != -1 && "Module const pool is broken!");
@@ -125,6 +134,8 @@
     output_vbr((unsigned)Slot, Out);
   }
   output_vbr((unsigned)Table.getValSlot(Type::VoidTy), Out);
+
+
   align32(Out);
 }
 
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index a8951e6..9056865 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -14,6 +14,7 @@
 #include "llvm/Analysis/SlotCalculator.h"
 #include "llvm/Module.h"
 #include "llvm/Method.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/BasicBlock.h"
 #include "llvm/ConstPoolVals.h"
 #include "llvm/iOther.h"
@@ -81,6 +82,7 @@
   }
 
   inline void write(const Module *M)         { processModule(M);      }
+  inline void write(const GlobalVariable *G) { processGlobal(G);      }
   inline void write(const Method *M)         { processMethod(M);      }
   inline void write(const BasicBlock *BB)    { processBasicBlock(BB); }
   inline void write(const Instruction *I)    { processInstruction(I); }
@@ -90,11 +92,12 @@
   void processModule(const Module *M);
   void processSymbolTable(const SymbolTable &ST);
   void processConstant(const ConstPoolVal *CPV);
+  void processGlobal(const GlobalVariable *GV);
   void processMethod(const Method *M);
   void processMethodArgument(const MethodArgument *MA);
   void processBasicBlock(const BasicBlock *BB);
   void processInstruction(const Instruction *I);
-
+  
   void writeOperand(const Value *Op, bool PrintType, bool PrintName = true);
 };
 
@@ -109,13 +112,22 @@
   // Loop over the symbol table, emitting all named constants...
   if (M->hasSymbolTable())
     processSymbolTable(*M->getSymbolTable());
-
+  
+  for_each(M->gbegin(), M->gend(), 
+	   bind_obj(this, &AssemblyWriter::processGlobal));
+	   
   Out << "implementation\n";
 
   // Output all of the methods...
   for_each(M->begin(), M->end(), bind_obj(this,&AssemblyWriter::processMethod));
 }
 
+void AssemblyWriter::processGlobal(const GlobalVariable *GV) {
+  Out << "global ";
+  if (GV->hasName()) Out << "%" << GV->getName() << " = ";
+  Out << GV->getType()->getDescription() << endl;
+}
+
 
 // processSymbolTable - Run through symbol table looking for named constants
 // if a named constant is found, emit it's declaration...
diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp
index bd342a2..0ec6411 100644
--- a/lib/VMCore/Function.cpp
+++ b/lib/VMCore/Function.cpp
@@ -1,6 +1,7 @@
 //===-- Method.cpp - Implement the Method class ------------------*- C++ -*--=//
 //
-// This file implements the Method class for the VMCore library.
+// This file implements the Method & GlobalVariable classes for the VMCore
+// library.
 //
 //===----------------------------------------------------------------------===//
 
@@ -9,9 +10,15 @@
 #include "llvm/SymbolTable.h"
 #include "llvm/Module.h"
 #include "llvm/Method.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/BasicBlock.h"
 #include "llvm/iOther.h"
 
+//===----------------------------------------------------------------------===//
+// Method Implementation
+//===----------------------------------------------------------------------===//
+
+
 // Instantiate Templates - This ugliness is the price we have to pay
 // for having a ValueHolderImpl.h file seperate from ValueHolder.h!  :(
 //
@@ -74,3 +81,25 @@
 void Method::dropAllReferences() {
   for_each(begin(), end(), std::mem_fun(&BasicBlock::dropAllReferences));
 }
+
+//===----------------------------------------------------------------------===//
+// GlobalVariable Implementation
+//===----------------------------------------------------------------------===//
+
+GlobalVariable::GlobalVariable(const Type *Ty, const string &Name = "")
+  : Value(Ty, Value::GlobalVal, Name), Parent(0) {
+  assert(Ty->isPointerType() && 
+	 (!Ty->isPointerType()->isArrayType() || // No unsized array pointers
+	  Ty->isPointerType()->isArrayType()->isSized()) &&
+	 "Global Variables must be pointers to a sized type!");
+}
+
+// Specialize setName to take care of symbol table majik
+void GlobalVariable::setName(const string &name, SymbolTable *ST) {
+  Module *P;
+  assert((ST == 0 || (!getParent() || ST == getParent()->getSymbolTable())) &&
+	 "Invalid symtab argument!");
+  if ((P = getParent()) && hasName()) P->getSymbolTable()->remove(this);
+  Value::setName(name);
+  if (P && getName() != "") P->getSymbolTableSure()->insert(this);
+}
diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp
index 4ab8bb0..5fc11d1 100644
--- a/lib/VMCore/Module.cpp
+++ b/lib/VMCore/Module.cpp
@@ -6,6 +6,7 @@
 
 #include "llvm/Module.h"
 #include "llvm/Method.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/BasicBlock.h"
 #include "llvm/InstrTypes.h"
 #include "llvm/ValueHolderImpl.h"
@@ -15,15 +16,18 @@
 // Instantiate Templates - This ugliness is the price we have to pay
 // for having a DefHolderImpl.h file seperate from DefHolder.h!  :(
 //
+template class ValueHolder<GlobalVariable, Module, Module>;
 template class ValueHolder<Method, Module, Module>;
 
 Module::Module()
   : Value(Type::VoidTy, Value::ModuleVal, ""), SymTabValue(this),
-    MethodList(this, this) {
+    GlobalList(this, this), MethodList(this, this) {
 }
 
 Module::~Module() {
   dropAllReferences();
+  GlobalList.delete_all();
+  GlobalList.setParent(0);
   MethodList.delete_all();
   MethodList.setParent(0);
 }
@@ -46,6 +50,12 @@
 // reduceApply - Apply the specified function to all of the methods in this 
 // module.  The result values are or'd together and the result is returned.
 //
+bool Module::reduceApply(bool (*Func)(GlobalVariable*)) {
+  return reduce_apply_bool(gbegin(), gend(), Func);
+}
+bool Module::reduceApply(bool (*Func)(const GlobalVariable*)) const {
+  return reduce_apply_bool(gbegin(), gend(), Func);
+}
 bool Module::reduceApply(bool (*Func)(Method*)) {
   return reduce_apply_bool(begin(), end(), Func);
 }
diff --git a/lib/VMCore/SlotCalculator.cpp b/lib/VMCore/SlotCalculator.cpp
index 9af5a38..cc7d4e5 100644
--- a/lib/VMCore/SlotCalculator.cpp
+++ b/lib/VMCore/SlotCalculator.cpp
@@ -12,6 +12,7 @@
 #include "llvm/Analysis/SlotCalculator.h"
 #include "llvm/Analysis/ConstantsScanner.h"
 #include "llvm/Method.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/Module.h"
 #include "llvm/BasicBlock.h"
 #include "llvm/ConstPoolVals.h"
@@ -68,13 +69,21 @@
 //
 void SlotCalculator::processModule() {
   SC_DEBUG("begin processModule!\n");
-  // Currently, the only module level declarations are methods and method
-  // prototypes.  We simply scavenge the types out of the methods, then add the
-  // methods themselves to the value table...
+
+  // Add all of the global variables to the value table...
+  //
+  for_each(TheModule->gbegin(), TheModule->gend(),
+	   bind_obj(this, &SlotCalculator::insertValue));
+
+  // Scavenge the types out of the methods, then add the methods themselves to
+  // the value table...
   //
   for_each(TheModule->begin(), TheModule->end(),  // Insert methods...
 	   bind_obj(this, &SlotCalculator::insertValue));
 
+  // Insert constants that are named at module level into the slot pool so that
+  // the module symbol table can refer to them...
+  //
   if (TheModule->hasSymbolTable() && !IgnoreNamedNodes) {
     SC_DEBUG("Inserting SymbolTable values:\n");
     processSymbolTable(TheModule->getSymbolTable());