[llvm-commits] [vmkit] r52778 - in /vmkit/trunk: include/debug.h lib/N3/VMCore/Assembly.cpp lib/N3/VMCore/Assembly.h lib/N3/VMCore/CLIJit.cpp lib/N3/VMCore/CLISignature.cpp lib/N3/VMCore/Opcodes.cpp lib/N3/VMCore/VMClass.cpp lib/N3/VMCore/VMClass.h lib/N3/VMCore/VirtualTables.cpp

Tilmann Scheller tilmann.scheller at googlemail.com
Thu Jun 26 02:41:08 PDT 2008


Author: tilmann
Date: Thu Jun 26 04:41:06 2008
New Revision: 52778

URL: http://llvm.org/viewvc/llvm-project?rev=52778&view=rev
Log:
add preliminary support for generic classes to N3

Modified:
    vmkit/trunk/include/debug.h
    vmkit/trunk/lib/N3/VMCore/Assembly.cpp
    vmkit/trunk/lib/N3/VMCore/Assembly.h
    vmkit/trunk/lib/N3/VMCore/CLIJit.cpp
    vmkit/trunk/lib/N3/VMCore/CLISignature.cpp
    vmkit/trunk/lib/N3/VMCore/Opcodes.cpp
    vmkit/trunk/lib/N3/VMCore/VMClass.cpp
    vmkit/trunk/lib/N3/VMCore/VMClass.h
    vmkit/trunk/lib/N3/VMCore/VirtualTables.cpp

Modified: vmkit/trunk/include/debug.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/debug.h?rev=52778&r1=52777&r2=52778&view=diff

==============================================================================
--- vmkit/trunk/include/debug.h (original)
+++ vmkit/trunk/include/debug.h Thu Jun 26 04:41:06 2008
@@ -10,6 +10,12 @@
 #ifndef DEBUG_H
 #define DEBUG_H
 
+#define DEBUG 0
+#define N3_COMPILE 0 //2
+#define N3_EXECUTE 0
+#define DEBUG_LOAD 0 //2
+#define N3_LOAD 0 //1
+
 #define ESC "\033["
 #define COLOR_NORMAL ""
 #define END "m"

Modified: vmkit/trunk/lib/N3/VMCore/Assembly.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Assembly.cpp?rev=52778&r1=52777&r2=52778&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/Assembly.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/Assembly.cpp Thu Jun 26 04:41:06 2008
@@ -215,6 +215,11 @@
   STRING(CONSTANT_FILE_NAME)
   BLOB(CONSTANT_FILE_HASH_VALUE))
 
+DEF_TABLE_MASK(METHOD_GenericParam, 4,
+  INT16(CONSTANT_GENERIC_PARAM_NUMBER)
+  INT16(CONSTANT_GENERIC_PARAM_FLAGS)
+  TYPE_OR_METHODDEF(CONSTANT_GENERIC_PARAM_OWNER)
+  STRING(CONSTANT_GENERIC_PARAM_NAME))
 
 void Header::print(mvm::PrintBuffer* buf) const {
   buf->write("Header<>");
@@ -332,7 +337,52 @@
   VMClass* cl = (VMClass*)loadedNameClasses->lookupOrCreate(CC, this, classDup);
   loadedTokenClasses->lookupOrCreate(token, cl);
   cl->token = token;
-  cl->assembly = this;
+  return cl;
+}
+
+static VMCommonClass* genClassDup(ClassNameCmp &cmp, Assembly* ass) {
+  VMClass* cl = gc_new(VMGenericClass)();
+  cl->initialise(ass->vm, false);
+  cl->name = cmp.name;
+  cl->nameSpace = cmp.nameSpace;
+  cl->virtualTracer = 0;
+  cl->staticInstance = 0;
+  cl->virtualInstance = 0;
+  cl->virtualType = 0;
+  cl->super = 0;
+  cl->status = hashed;
+  cl->assembly = ass;
+  return cl;
+}
+
+VMGenericClass* Assembly::constructGenericClass(const UTF8* name,
+                                         const UTF8* nameSpace, std::vector<VMCommonClass*> genArgs, uint32 token) {
+  uint32 size = name->size + 2;
+  sint32 i = 0;
+  for (std::vector<VMCommonClass*>::iterator it = genArgs.begin(), e = genArgs.end(); it!= e; ++it) {
+    size += (*it)->name->size + 1;
+  }
+  uint16* buf = (uint16*) alloca(sizeof(uint16) * size);
+  for (i = 0; i < name->size; i++) {
+    buf[i] = name->at(i);
+  }
+  buf[i++] = '<';
+  for (std::vector<VMCommonClass*>::iterator it = genArgs.begin(), e = genArgs.end(); it!= e; ++it) {
+    for (int j = 0; j < (*it)->name->size; i++, j++) {
+      buf[i] = (*it)->name->at(j);
+    }
+    buf[i++] = ',';
+  }
+  buf[i] = '>';
+  const UTF8* genName = UTF8::readerConstruct(VMThread::get()->vm, buf, size);
+  printf("%s\n", genName->printString());
+  
+  ClassNameCmp CC(genName, nameSpace);
+  VMGenericClass* cl = (VMGenericClass*) loadedNameClasses->lookupOrCreate(CC, this, genClassDup);
+  
+  cl->genericParams = genArgs; // TODO GC safe?
+  cl->token = token;
+  
   return cl;
 }
 
@@ -377,6 +427,7 @@
   ass->assemblyRefs = 0;
   ass->isRead = false;
   ass->name = name;
+  ass->currGenericClass = 0;
   return ass;
 }
 
@@ -429,7 +480,7 @@
   unimplemented,                // 0x27
   METHOD_ManifestResource,      // 0x28
   METHOD_NestedClass,           // 0x29
-  unimplemented,                // 0x2A
+  METHOD_GenericParam,          // 0x2A
   METHOD_MethodSpec,            // 0x2B
   METHOD_GenericParamConstraint,// 0x2C
   unimplemented,
@@ -496,7 +547,7 @@
   "unimplemented",                // 0x27
   "METHOD_ManifestResource",      // 0x28
   "METHOD_NestedClass",           // 0x29
-  "unimplemented",                // 0x2A
+  "METHOD_GenericParam",          // 0x2A
   "METHOD_MethodSpec",            // 0x2B
   "METHOD_GenericParamConstraint", // 0x2C
   "unimplemented",
@@ -909,6 +960,10 @@
 }
 
 VMClass* Assembly::readTypeDef(N3* vm, uint32 index) {
+  return readTypeDef(vm, index, (std::vector<VMCommonClass*>) 0);
+}
+
+VMClass* Assembly::readTypeDef(N3* vm, uint32 index, std::vector<VMCommonClass*> genArgs) {
   uint32 token = (CONSTANT_TypeDef << 24) + index;
   uint32 stringOffset = CLIHeader->stringStream->realOffset;
 
@@ -929,9 +984,18 @@
   //Table* methodTable  = CLIHeader->tables[CONSTANT_MethodDef];
   //uint32 methodSize   = methodTable->rowsNumber;
 
-  VMClass* type = constructClass(readString(vm, name + stringOffset),
+  VMClass* type;
+  
+  if (genArgs == (std::vector<VMCommonClass*>) 0) {
+    type = constructClass(readString(vm, name + stringOffset),
+                          readString(vm, nameSpace + stringOffset),
+                          token);
+  } else {
+	// generic type
+	type = constructGenericClass(readString(vm, name + stringOffset),
                                  readString(vm, nameSpace + stringOffset),
-                                 token);
+                                 genArgs, token);
+  }
 
   type->vm = vm;
 
@@ -991,10 +1055,15 @@
   }
 }
 
+VMCommonClass* Assembly::loadType(N3* vm, uint32 token, bool resolve,
+                            bool resolveStatic, bool clinit, bool dothrow) {
+	return loadType(vm, token, resolve, resolveStatic, clinit, dothrow, (std::vector<VMCommonClass*>) 0);
+}
 
 
 VMCommonClass* Assembly::loadType(N3* vm, uint32 token, bool resolve,
-                            bool resolveStatic, bool clinit, bool dothrow) {
+                            bool resolveStatic, bool clinit, bool dothrow,
+                            std::vector<VMCommonClass*> genArgs) {
   
   VMCommonClass* type = lookupClassFromToken(token);
   if (!type || type->status == hashed) {
@@ -1002,7 +1071,7 @@
     uint32 index = token & 0xffff;
 
     if (table == CONSTANT_TypeDef) {
-      type = readTypeDef(vm, index);
+      type = readTypeDef(vm, index, genArgs);
     } else if (table == CONSTANT_TypeRef) {
       type = readTypeRef(vm, index);
     } else if (table == CONSTANT_TypeSpec) {
@@ -1027,6 +1096,9 @@
 }
 
 void Assembly::readClass(VMCommonClass* cl) {
+  // temporarily store the class being read in case it is a generic class
+  currGenericClass = dynamic_cast<VMGenericClass*>(cl);
+	
   uint32 index = cl->token & 0xffff;
   Table* typeTable = CLIHeader->tables[CONSTANT_TypeDef];
   uint32 typeSize = typeTable->rowsNumber;
@@ -1077,6 +1149,9 @@
       }
     }
   }
+  
+  // we have stopped reading a generic class
+  currGenericClass = 0;
 }
 
 void Assembly::readCustomAttributes(uint32 offset, std::vector<llvm::GenericValue>& args, VMMethod* meth) {
@@ -1233,6 +1308,8 @@
   if (rva) {
     meth->offset = textSection->rawAddress + 
                    (rva - textSection->virtualAddress);
+  } else {
+    meth->offset = 0;
   }
   
   if (paramList && paramTable != 0 && paramList <= paramSize) {
@@ -1580,16 +1657,26 @@
     case 3: VMThread::get()->vm->error("implement me %d", table); break;
     case 4: {
       VMClass* type = (VMClass*)readTypeSpec(vm, index);
-      VMMethod* meth = gc_new(VMMethod)();
-      bool virt = extractMethodSignature(offset, type, args);
-      bool structReturn = false;
-      const llvm::FunctionType* signature = VMMethod::resolveSignature(args, virt, structReturn);
-      meth->_signature = signature;
-      meth->classDef = type;
-      meth->name = name;
-      meth->virt = virt;
-      meth->structReturn = structReturn;
-      return meth;
+      
+      VMGenericClass* genClass = dynamic_cast<VMGenericClass*>(type);
+
+      if (genClass) {
+        bool virt = extractMethodSignature(offset, type, args);
+        VMMethod* meth = type->lookupMethod(name, args, !virt, true);
+        return meth;
+      } else {
+	    VMMethod* meth = gc_new(VMMethod)();
+	    bool virt = extractMethodSignature(offset, type, args);
+	    bool structReturn = false;
+	    const llvm::FunctionType* signature = VMMethod::resolveSignature(args, virt, structReturn);
+	    meth->_signature = signature;
+	    meth->classDef = type;
+	    meth->name = name;
+	    meth->virt = virt;
+	    meth->structReturn = structReturn;
+	    meth->parameters = args; // TODO check whether this fix is correct
+	    return meth;
+      }
     }
     default:
       VMThread::get()->vm->error("unknown MemberRefParent tag %d", table);

Modified: vmkit/trunk/lib/N3/VMCore/Assembly.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Assembly.h?rev=52778&r1=52777&r2=52778&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/Assembly.h (original)
+++ vmkit/trunk/lib/N3/VMCore/Assembly.h Thu Jun 26 04:41:06 2008
@@ -42,6 +42,7 @@
 class UTF8;
 class VirtualMachine;
 class VMClass;
+class VMGenericClass;
 class VMClassArray;
 class VMClassPointer;
 class VMCommonClass;
@@ -142,6 +143,10 @@
                                uint32 dims);
   VMClass*      constructClass(const UTF8* name,
                                const UTF8* nameSpace, uint32 token);
+  VMGenericClass* constructGenericClass(const UTF8* name,
+                                        const UTF8* nameSpace,
+                                        std::vector<VMCommonClass*> genArgs,
+                                        uint32 token);
   VMField*      constructField(VMClass* cl, const UTF8* name,
                                VMCommonClass* signature, uint32 token);
   VMMethod*     constructMethod(VMClass* cl, const UTF8* name,
@@ -155,6 +160,9 @@
   ClassTokenMap* loadedTokenClasses;
   MethodTokenMap* loadedTokenMethods;
   FieldTokenMap* loadedTokenFields;
+  
+  // helper which points to the current generic class while it is being read in readClass()
+  VMGenericClass* currGenericClass;
 
   mvm::Lock* lockVar;
   mvm::Cond* condVar;
@@ -202,6 +210,8 @@
   uint32 getTypeDefTokenFromMethod(uint32 token);
   VMCommonClass* loadType(N3* vm, uint32 token, bool resolveFunc, bool resolve,
                           bool clinit, bool dothrow);
+  VMCommonClass* loadType(N3* vm, uint32 token, bool resolveFunc, bool resolve,
+                          bool clinit, bool dothrow, std::vector<VMCommonClass*> genArgs);
   
   VMCommonClass* loadTypeFromName(const UTF8* name, const UTF8* nameSpace, 
                                   bool resolveFunc, bool resolve,
@@ -213,6 +223,7 @@
   VMField* readField(uint32 index, VMCommonClass* cl);
   Param* readParam(uint32 index, VMMethod* meth);
   VMClass* readTypeDef(N3* vm, uint32 index);
+  VMClass* readTypeDef(N3* vm, uint32 index, std::vector<VMCommonClass*> genArgs);
   VMCommonClass* readTypeSpec(N3* vm, uint32 index);
   Assembly* readAssemblyRef(N3* vm, uint32 index);
   VMCommonClass* readTypeRef(N3* vm, uint32 index);
@@ -704,6 +715,11 @@
 #define CONSTANT_FILE_NAME 1
 #define CONSTANT_FILE_HASH_VALUE 2
 
+#define CONSTANT_GENERIC_PARAM_NUMBER 0
+#define CONSTANT_GENERIC_PARAM_FLAGS 1
+#define CONSTANT_GENERIC_PARAM_OWNER 2
+#define CONSTANT_GENERIC_PARAM_NAME 3
+
 } // end namespace n3
 
 #endif

Modified: vmkit/trunk/lib/N3/VMCore/CLIJit.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLIJit.cpp?rev=52778&r1=52777&r2=52778&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/CLIJit.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/CLIJit.cpp Thu Jun 26 04:41:06 2008
@@ -7,9 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#define DEBUG 0
-#define N3_COMPILE 0
-#define N3_EXECUTE 0
+//#define DEBUG 0
+//#define N3_COMPILE 0
+//#define N3_EXECUTE 0
 
 #include "debug.h"
 #include "types.h"
@@ -458,12 +458,23 @@
   CLIJit* jit = gc_new(CLIJit)();
   jit->compilingClass = meth->classDef; 
   jit->compilingMethod = meth;
+  
+  // save current class in case of recursive calls to compile()
+  VMGenericClass* old = jit->compilingClass->assembly->currGenericClass;
+  // temporarily store the class being compiled in case it is a generic class
+  jit->compilingClass->assembly->currGenericClass = dynamic_cast<VMGenericClass*>(jit->compilingClass);
+  
+  
   jit->unifiedUnreachable = unifiedUnreachable;
   jit->inlineMethods = inlineMethods;
   jit->inlineMethods[meth] = true;
   Instruction* ret = jit->inlineCompile(llvmFunction, currentBlock, 
                                         currentExceptionBlock, args);
   inlineMethods[meth] = false;
+  
+  // restore saved class
+  jit->compilingClass = old;
+  
   return ret;
 }
 
@@ -915,7 +926,7 @@
 Function* CLIJit::compileNative() {
   PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "native compile %s\n",
               compilingMethod->printString());
-  
+    
   const FunctionType *funcType = compilingMethod->getSignature();
   
   Function* func = llvmFunction = compilingMethod->methPtr;
@@ -1409,6 +1420,11 @@
   jit->compilingClass = cl; 
   jit->compilingMethod = meth;
 
+  // save current class in case of recursive calls to compile()
+  VMGenericClass* old = cl->assembly->currGenericClass;
+  // temporarily store the class being compiled in case it is a generic class
+  cl->assembly->currGenericClass = dynamic_cast<VMGenericClass*>(cl);
+  
   meth->getSignature();
   if (isInternal(meth->implFlags)) {
     return jit->compileNative();
@@ -1417,6 +1433,9 @@
   } else {
     return jit->compileFatOrTiny();
   }
+  
+  // restore saved class
+  cl->assembly->currGenericClass = old;
 }
 
 llvm::Function *VMMethod::compiledPtr() {

Modified: vmkit/trunk/lib/N3/VMCore/CLISignature.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/CLISignature.cpp?rev=52778&r1=52777&r2=52778&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/CLISignature.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/CLISignature.cpp Thu Jun 26 04:41:06 2008
@@ -136,9 +136,11 @@
 }
 
 static VMCommonClass* METHOD_ElementTypeVar(uint32 op, Assembly* ass, uint32& offset) {
+  uint32 number = ass->uncompressSignature(offset);
+  return ass->currGenericClass->genericParams[number];
   //uint32 type = READ_U4(ass->bytes, offset);
-  VMThread::get()->vm->error("implement me");
-  return 0;
+  //VMThread::get()->vm->error("implement me");
+  //return 0;
 }
 
 static VMCommonClass* METHOD_ElementTypeArray(uint32 op, Assembly* ass, uint32& offset) {
@@ -167,8 +169,54 @@
 }
 
 static VMCommonClass* METHOD_ElementTypeGenericInst(uint32 op, Assembly* ass, uint32& offset) {
-  VMThread::get()->vm->error("implement me");
-  return 0;
+  // offset points to (CLASS | VALUETYPE) TypeDefOrRefEncoded
+
+  // skip generic type definition
+  offset++; // this is (CLASS | VALUETYPE)
+
+  // save starting offset for later use
+  uint32 genericTypeOffset = offset;
+  
+  ass->uncompressSignature(offset); // TypeDefOrRefEncoded
+
+  //VMCommonClass* cl = ass->exploreType(offset);
+  
+  uint32 argCount = ass->uncompressSignature(offset);
+  
+  std::vector<VMCommonClass*> args;
+  
+  // Get generic arguments.
+  for (uint32 i = 0; i < argCount; ++i) {
+	  args.push_back(ass->exploreType(offset));
+  }
+
+  // save offset
+  uint32 endOffset = offset;
+  // restore starting offset
+  offset = genericTypeOffset;
+  
+  // TypeDefOrRefEncoded
+  uint32 value = ass->uncompressSignature(offset);
+  uint32 table = value & 3;
+  uint32 index = value >> 2;
+  uint32 token = 0;
+
+  switch (table) {
+    case 0: table = CONSTANT_TypeDef; break;
+    case 1: table = CONSTANT_TypeRef; break;
+    case 2: table = CONSTANT_TypeSpec; break;
+    default:
+      VMThread::get()->vm->error("unknown TypeDefOrRefEncoded %d", index);
+      break;
+  }
+
+  token = (table << 24) + index;
+  VMCommonClass* cl = ass->loadType((N3*)(VMThread::get()->vm), token, false, 
+                                    false, false, true, args);
+  // restore endOffset
+  offset = endOffset;
+  
+  return cl;
 }
 
 static VMCommonClass* METHOD_ElementTypeTypedByRef(uint32 op, Assembly* ass, uint32& offset) {

Modified: vmkit/trunk/lib/N3/VMCore/Opcodes.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/Opcodes.cpp?rev=52778&r1=52777&r2=52778&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/Opcodes.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/Opcodes.cpp Thu Jun 26 04:41:06 2008
@@ -7,9 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#define DEBUG 0
-#define N3_COMPILE 0
-#define N3_EXECUTE 0
+//#define DEBUG 0
+//#define N3_COMPILE 0
+//#define N3_EXECUTE 0
 
 #include <string.h>
 

Modified: vmkit/trunk/lib/N3/VMCore/VMClass.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMClass.cpp?rev=52778&r1=52777&r2=52778&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/VMClass.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/VMClass.cpp Thu Jun 26 04:41:06 2008
@@ -395,6 +395,7 @@
 
 void VMCommonClass::resolveType(bool stat, bool clinit) {
   VMCommonClass* cl = this;
+  //printf("*** Resolving: %s\n", cl->printString());
   if (cl->status < resolved) {
     cl->aquire();
     int status = cl->status;
@@ -815,3 +816,7 @@
   }
   return true;
 }
+
+void VMGenericClass::print(mvm::PrintBuffer* buf) const {
+  buf->write("Generic Class");
+}

Modified: vmkit/trunk/lib/N3/VMCore/VMClass.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMClass.h?rev=52778&r1=52777&r2=52778&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/VMClass.h (original)
+++ vmkit/trunk/lib/N3/VMCore/VMClass.h Thu Jun 26 04:41:06 2008
@@ -147,6 +147,15 @@
   uint32 explicitLayoutSize;
 };
 
+class VMGenericClass : public VMClass {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void TRACER;
+
+  std::vector<VMCommonClass*> genericParams;
+};
+
 class VMClassArray : public VMCommonClass {
 public:
   static VirtualTable* VT;

Modified: vmkit/trunk/lib/N3/VMCore/VirtualTables.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VirtualTables.cpp?rev=52778&r1=52777&r2=52778&view=diff

==============================================================================
--- vmkit/trunk/lib/N3/VMCore/VirtualTables.cpp (original)
+++ vmkit/trunk/lib/N3/VMCore/VirtualTables.cpp Thu Jun 26 04:41:06 2008
@@ -40,6 +40,7 @@
   INIT(UTF8);
   INIT(VMCommonClass);
   INIT(VMClass);
+  INIT(VMGenericClass);
   INIT(VMClassArray);
   INIT(VMClassPointer);
   INIT(VMMethod);
@@ -169,6 +170,11 @@
   outerClass->MARK_AND_TRACE;
 }
 
+void VMGenericClass::TRACER {
+  VMClass::PARENT_TRACER;
+  TRACE_VECTOR(VMCommonClass*, genericParams, std::allocator);
+}
+
 void VMClassArray::TRACER {
   VMCommonClass::PARENT_TRACER;
   baseClass->MARK_AND_TRACE;





More information about the llvm-commits mailing list