[llvm-commits] CVS: llvm-java/lib/Compiler/Compiler.cpp

Alkis Evlogimenos alkis at cs.uiuc.edu
Thu Aug 5 11:22:53 PDT 2004



Changes in directory llvm-java/lib/Compiler:

Compiler.cpp updated: 1.76 -> 1.77
---
Log message:

Introduce vtables. As we do not allocate objects yet this do not
really work, but the code generated seems fine. The implementation
needs some refactoring. This will happen next.


---
Diffs of the changes:  (+125 -7)

Index: llvm-java/lib/Compiler/Compiler.cpp
diff -u llvm-java/lib/Compiler/Compiler.cpp:1.76 llvm-java/lib/Compiler/Compiler.cpp:1.77
--- llvm-java/lib/Compiler/Compiler.cpp:1.76	Thu Aug  5 07:53:53 2004
+++ llvm-java/lib/Compiler/Compiler.cpp	Thu Aug  5 13:22:43 2004
@@ -149,7 +149,7 @@
 
     struct VTableInfo {
       VTableInfo() : vtable(NULL) { }
-      ConstantStruct* vtable;
+      GlobalVariable* vtable;
       typedef std::map<std::string, unsigned> Method2IndexMap;
       Method2IndexMap m2iMap;
     };
@@ -244,7 +244,7 @@
       ClassFile* cf = ClassFile::getClassFile(className);
       ClassInfo& ci = c2ciMap_[className];
       assert(!ci.type && ci.f2iMap.empty() &&
-             "got already initialized Classinfo!");
+             "got already initialized ClassInfo!");
       ci.type = OpaqueType::get();
 
       std::vector<const Type*> elements;
@@ -257,7 +257,8 @@
         // this is java/lang/Object so we must add the opaque
         // llvm_java_base type first
         Type* base = OpaqueType::get();
-        module_->addTypeName("llvm_java_base", base);
+        module_->addTypeName("<llvm_java_base>", base);
+        ci.f2iMap.insert(std::make_pair("<llvm_java_base>", elements.size()));
         elements.push_back(base);
       }
 
@@ -281,7 +282,77 @@
       return ci;
     }
 
-    //const VTableInfo& getVTableInfo(const std::string& className);
+    const VTableInfo& getVTableInfo(const std::string& className) {
+      Class2VTableInfoMap::iterator it = c2viMap_.lower_bound(className);
+      if (it != c2viMap_.end() && it->first == className)
+        return it->second;
+
+      DEBUG(std::cerr << "Building VTableInfo for: " << className << '\n');
+      ClassFile* cf = ClassFile::getClassFile(className);
+      VTableInfo& vi = c2viMap_[className];
+      assert(!vi.vtable && vi.m2iMap.empty() &&
+             "got already initialized VTableInfo!");
+
+      std::vector<const Type*> elements;
+      std::vector<llvm::Constant*> init;
+      ConstantClass* super = cf->getSuperClass();
+      const VTableInfo* superVI =
+        super ? &getVTableInfo(super->getName()->str()) : NULL;
+
+      if (superVI) {
+        // copy all the types from the super class' vtable
+        assert(superVI->vtable && "No vtable found for super class!");
+        ConstantStruct* superInit =
+          cast<ConstantStruct>(superVI->vtable->getInitializer());
+        const StructType* superVTableTy = superInit->getType();
+        std::copy(superVTableTy->element_begin(),
+                  superVTableTy->element_end(),
+                  std::back_inserter(elements));
+        for (unsigned i = 0, e = superInit->getNumOperands(); i != e; ++i)
+            init.push_back(superInit->getOperand(i));
+        vi.m2iMap = superVI->m2iMap;
+        }
+//         else {
+//           // this is java/lang/Object so we must add the opaque
+//           // llvm_java_vtable_base type first
+//           Type* baseVTable = OpaqueType::get();
+//           module_->addTypeName("<llvm_java_vtable_base>", baseVTable);
+//           elements.push_back(baseVTable);
+//           init.push_back(llvm::Constant::getNullValue(baseVTable));
+//         }
+
+        const Methods& methods = cf->getMethods();
+        init.resize(elements.size(), NULL);
+
+        for (unsigned i = 0, e = methods.size(); i != e; ++i) {
+          Method* method = methods[i];
+          if (!method->isStatic() && method->getName()->str() != "<init>") {
+            std::string methodDescr =
+              method->getName()->str() +
+              method->getDescriptor()->str();
+            unsigned& index = vi.m2iMap[methodDescr];
+            Function* vfun = module_->getOrInsertFunction
+              (className + '/' + methodDescr,
+               cast<FunctionType>(getType(method->getDescriptor(),
+                                          getClassInfo(className).type)));
+            toCompileFunctions_.insert(vfun);
+            if (!index) {
+              index = elements.size();
+              elements.push_back(vfun->getType());
+              init.resize(elements.size(), NULL);
+            }
+            init[index] = vfun;
+            DEBUG(std::cerr << index << " = " << methodDescr << '\n');
+          }
+        }
+
+        vi.vtable = new GlobalVariable(StructType::get(elements),
+                                       true, GlobalVariable::ExternalLinkage,
+                                       ConstantStruct::get(init),
+                                       className + "<vtable>",
+                                       module_);
+        return vi;
+    }
 
     Value* getOrCreateLocal(unsigned index, Type* type) {
       if (!locals_[index] ||
@@ -313,12 +384,20 @@
         (ConstantFieldRef*)(cf_->getConstantPool()[index]);
       ConstantNameAndType* nameAndType = fieldRef->getNameAndType();
 
+      return getField(bcI,
+                      fieldRef->getClass()->getName()->str(),
+                      nameAndType->getName()->str(),
+                      ptr);
+    }
+
+    Value* getField(unsigned bcI,
+                    std::string className,
+                    const std::string& fieldName,
+                    Value* ptr) {
       // Cast ptr to correct type
-      std::string className = fieldRef->getClass()->getName()->str();
       ptr = new CastInst(ptr, PointerType::get(getClassInfo(className).type),
                          TMP, getBBAt(bcI));
       ClassFile* classfile = ClassFile::getClassFile(className);
-      std::string fieldName = nameAndType->getName()->str();
 
       // deref pointer
       std::vector<Value*> indices(1, ConstantUInt::get(Type::UIntTy, 0));
@@ -831,7 +910,46 @@
     }
 
     void do_invokevirtual(unsigned bcI, unsigned index) {
-      assert(0 && "not implemented");
+      ConstantMethodRef* methodRef =
+        (ConstantMethodRef*)(cf_->getConstantPool()[index]);
+      ConstantNameAndType* nameAndType = methodRef->getNameAndType();
+
+      const std::string className = methodRef->getClass()->getName()->str();
+      const ClassInfo& ci = getClassInfo(className);
+      const VTableInfo& vi = getVTableInfo(className);
+
+      std::string methodDescr =
+        nameAndType->getName()->str() +
+        nameAndType->getDescriptor()->str();
+
+      Value* objRef = opStack_.top(); // do not pop
+      objRef = new CastInst(objRef, PointerType::get(ci.type),
+                            "this", getBBAt(bcI));
+      Value* vtable = getField(bcI, className, "<llvm_java_base>", objRef);
+      vtable = new CastInst(vtable, PointerType::get(vi.vtable->getType()),
+                            TMP, getBBAt(bcI));
+      vtable = new LoadInst(vtable, TMP, getBBAt(bcI));
+      std::vector<Value*> indices(1, ConstantUInt::get(Type::UIntTy, 0));
+      assert(vi.m2iMap.find(methodDescr) != vi.m2iMap.end() &&
+             "could not find slot for virtual function!");
+      unsigned vSlot = vi.m2iMap.find(methodDescr)->second;
+      indices.push_back(ConstantUInt::get(Type::UIntTy, vSlot));
+      Value* vfun = new LoadInst
+        (new GetElementPtrInst(vtable, indices, TMP, getBBAt(bcI)), TMP,
+         getBBAt(bcI));
+
+      const FunctionType* vfunTy = cast<FunctionType>
+        (cast<PointerType>(vfun->getType())->getElementType());
+      std::vector<Value*> params(vfunTy->getNumParams(), NULL);
+      for (unsigned i = 0, e = vfunTy->getNumParams(); i != e; ++i) {
+        Value* p = opStack_.top(); opStack_.pop();
+        const Type* paramTy = vfunTy->getParamType(i);
+        params[i] = p->getType() == paramTy ? p :
+          new CastInst(p, paramTy, TMP, getBBAt(bcI));
+      }
+
+      Value* r = new CallInst(vfun, params, TMP, getBBAt(bcI));
+      opStack_.push(r);
     }
 
     void do_invokespecial(unsigned bcI, unsigned index) {






More information about the llvm-commits mailing list