[llvm-commits] CVS: llvm-java/lib/Compiler/Compiler.cpp
Alkis Evlogimenos
alkis at cs.uiuc.edu
Wed Sep 15 11:06:58 PDT 2004
Changes in directory llvm-java/lib/Compiler:
Compiler.cpp updated: 1.99 -> 1.100
---
Log message:
Add typeinfo for interfaces. Implement the invokeinterface bytecode.
---
Diffs of the changes: (+245 -65)
Index: llvm-java/lib/Compiler/Compiler.cpp
diff -u llvm-java/lib/Compiler/Compiler.cpp:1.99 llvm-java/lib/Compiler/Compiler.cpp:1.100
--- llvm-java/lib/Compiler/Compiler.cpp:1.99 Wed Sep 15 01:11:08 2004
+++ llvm-java/lib/Compiler/Compiler.cpp Wed Sep 15 13:06:47 2004
@@ -37,7 +37,8 @@
#define LLVM_JAVA_STATIC_INIT "llvm_java_static_init"
-#define LLVM_JAVA_ISINSTANCEOF "llvm_java_IsInstanceOf"
+#define LLVM_JAVA_ISINSTANCEOF "llvm_java_IsInstanceOf"
+#define LLVM_JAVA_GETOBJECTCLASS "llvm_java_GetObjectClass"
using namespace llvm;
using namespace llvm::Java;
@@ -133,10 +134,13 @@
FunctionSet toCompileFunctions_;
struct ClassInfo {
- ClassInfo() : type(NULL) { }
+ ClassInfo() : type(NULL), interfaceIdx(0) { }
Type* type;
+ unsigned interfaceIdx;
typedef std::map<std::string, unsigned> Field2IndexMap;
Field2IndexMap f2iMap;
+
+ static unsigned InterfaceCount;
};
typedef std::map<ClassFile*, ClassInfo> Class2ClassInfoMap;
Class2ClassInfoMap c2ciMap_;
@@ -144,9 +148,12 @@
struct VTableInfo {
VTableInfo() : vtable(NULL) { }
GlobalVariable* vtable;
- std::vector<GlobalVariable*> superVtables;
+ std::vector<llvm::Constant*> superVtables;
typedef std::map<std::string, unsigned> Method2IndexMap;
Method2IndexMap m2iMap;
+
+ static StructType* VTableTy;
+ static StructType* TypeInfoTy;
};
typedef std::map<ClassFile*, VTableInfo> Class2VTableInfoMap;
Class2VTableInfoMap c2viMap_;
@@ -285,6 +292,7 @@
assert(ci.type && "ClassInfo not initialized properly!");
emitStaticInitializers(cf);
+ DEBUG(std::cerr << "Built ClassInfo for: java/lang/Object\n");
}
void initializeVTableInfoMap() {
@@ -316,9 +324,11 @@
elements.push_back(PointerType::get(PointerType::get(VTtype)));
init.push_back(llvm::Constant::getNullValue(elements[3]));
- StructType* typeInfoTy = StructType::get(elements);
- module_->addTypeName(LLVM_JAVA_OBJECT_TYPEINFO, typeInfoTy);
- llvm::Constant* typeInfoInit = ConstantStruct::get(typeInfoTy, init);
+ // this is a static variable
+ VTableInfo::TypeInfoTy = StructType::get(elements);
+ module_->addTypeName(LLVM_JAVA_OBJECT_TYPEINFO, VTableInfo::TypeInfoTy);
+ llvm::Constant* typeInfoInit =
+ ConstantStruct::get(VTableInfo::TypeInfoTy, init);
// now that we have both the type and initializer for the
// llvm_java_object_typeinfo struct we can start adding the
@@ -363,15 +373,16 @@
PATypeHolder holder = VTtype;
cast<OpaqueType>(VTtype)->refineAbstractTypeTo(StructType::get(elements));
- VTtype = cast<StructType>(holder.get());
- vi.vtable = new GlobalVariable(VTtype,
+ VTableInfo::VTableTy = cast<StructType>(holder.get());
+ module_->addTypeName("java/lang/Object<vtable>", VTableInfo::VTableTy);
+
+ vi.vtable = new GlobalVariable(VTableInfo::VTableTy,
true, GlobalVariable::ExternalLinkage,
ConstantStruct::get(init),
"java/lang/Object<vtable>",
module_);
- // java/lang/Object doesn't have a superVtables global as its
- // array of superclass vtable pointers is empty
+ DEBUG(std::cerr << "Built VTableInfo for: java/lang/Object\n");
}
void initializeTypeMaps() {
@@ -380,16 +391,21 @@
}
const ClassInfo& getClassInfo(ClassFile* cf) {
- const std::string& className = cf->getThisClass()->getName()->str();
Class2ClassInfoMap::iterator it = c2ciMap_.lower_bound(cf);
if (it != c2ciMap_.end() && it->first == cf)
return it->second;
+ const std::string& className = cf->getThisClass()->getName()->str();
DEBUG(std::cerr << "Building ClassInfo for: " << className << '\n');
ClassInfo& ci = c2ciMap_[cf];
assert(!ci.type && ci.f2iMap.empty() &&
"got already initialized ClassInfo!");
+
+ // get the interface id
+ if (cf->isInterface())
+ ci.interfaceIdx = ClassInfo::InterfaceCount++;
+
ci.type = OpaqueType::get();
std::vector<const Type*> elements;
@@ -411,59 +427,148 @@
PATypeHolder holder = ci.type;
cast<OpaqueType>(ci.type)->refineAbstractTypeTo(StructType::get(elements));
ci.type = holder.get();
+
+ assert(ci.type && "ClassInfo not initialized properly!");
DEBUG(std::cerr << "Adding " << className << " = "
<< *ci.type << " to type map\n");
module_->addTypeName(className, ci.type);
-
- assert(ci.type && "ClassInfo not initialized properly!");
emitStaticInitializers(cf);
+ DEBUG(std::cerr << "Built ClassInfo for: " << className << '\n');
return ci;
}
- llvm::Constant* getClassTypeInfo(ClassFile* cf,
- const VTableInfo& vi,
- const VTableInfo& superVI) const {
- // llvm_java_object_typeinfo has four fields: depth, a pointer
- // to the superclasses vtable pointers, a count for interfaces
- // and a pointer to the interfaces vtable pointers
- const std::string& className = cf->getThisClass()->getName()->str();
+ std::pair<unsigned,llvm::Constant*>
+ buildSuperClassesVTables(ClassFile* cf, const VTableInfo& vi) const {
+ ArrayType* vtablesArrayTy =
+ ArrayType::get(PointerType::get(VTableInfo::VTableTy),
+ vi.superVtables.size());
+
+ GlobalVariable* vtablesArray = new GlobalVariable(
+ vtablesArrayTy,
+ true,
+ GlobalVariable::ExternalLinkage,
+ ConstantArray::get(vtablesArrayTy, vi.superVtables),
+ cf->getThisClass()->getName()->str() + "<superclassesvtables>",
+ module_);
+
+ return std::make_pair(
+ vi.superVtables.size(),
+ ConstantExpr::getGetElementPtr(
+ vtablesArray,
+ std::vector<llvm::Constant*>(2, ConstantUInt::get(Type::UIntTy, 0))));
+ }
+
+ llvm::Constant* buildInterfaceVTable(ClassFile* cf, ClassFile* interface) {
+
+ const VTableInfo& classVI = getVTableInfo(cf);
+ const VTableInfo& interfaceVI = getVTableInfo(interface);
+ const Methods& methods = interface->getMethods();
+
+ // the size of the initializer will be 1 greater than the number
+ // of methods for this interface (the first slot is the typeinfo
+ // struct
+ std::vector<llvm::Constant*> init(interfaceVI.m2iMap.size()+1, NULL);
+ init[0] = llvm::Constant::getNullValue(VTableInfo::TypeInfoTy);
+
+ for (VTableInfo::Method2IndexMap::const_iterator
+ i = interfaceVI.m2iMap.begin(), e = interfaceVI.m2iMap.end();
+ i != e; ++i) {
+ std::vector<llvm::Constant*> indices;
+ indices.reserve(2);
+ indices.push_back(ConstantUInt::get(Type::UIntTy, 0));
+ assert(classVI.m2iMap.find(i->first) != classVI.m2iMap.end() &&
+ "Interface method not found in class definition!");
+ unsigned classMethodIdx = classVI.m2iMap.find(i->first)->second;
+ indices.push_back(ConstantUInt::get(Type::UIntTy, classMethodIdx));
+ init[i->second] =
+ ConstantExpr::getGetElementPtr(classVI.vtable, indices);
+ }
+
+ llvm::Constant* vtable = ConstantStruct::get(init);
+ const std::string& globalName =
+ cf->getThisClass()->getName()->str() + '+' +
+ interface->getThisClass()->getName()->str() + "<vtable>";
+ module_->addTypeName(globalName, vtable->getType());
+
+ return new GlobalVariable(
+ vtable->getType(),
+ true,
+ GlobalVariable::ExternalLinkage,
+ vtable,
+ globalName,
+ module_);
+ }
+ std::pair<int, llvm::Constant*>
+ buildInterfacesVTables(ClassFile* cf, const VTableInfo& vi) {
+
+ std::vector<llvm::Constant*> vtables;
+ const Classes& interfaces = cf->getInterfaces();
+ llvm::Constant* nullVTable =
+ llvm::Constant::getNullValue(PointerType::get(VTableInfo::VTableTy));
+
+ for (unsigned i = 0, e = interfaces.size(); i != e; ++i) {
+ ClassFile* interface = ClassFile::get(interfaces[i]->getName()->str());
+ assert(interface->isInterface() &&
+ "Class in interfaces list is not an interface!");
+ const ClassInfo& interfaceCI = getClassInfo(interface);
+ vtables.resize(interfaceCI.interfaceIdx, nullVTable);
+ vtables[interfaceCI.interfaceIdx] = buildInterfaceVTable(cf, interface);
+ }
+
+ ArrayType* interfacesArrayTy =
+ ArrayType::get(PointerType::get(VTableInfo::VTableTy), vtables.size());
+
+ const std::string& globalName =
+ cf->getThisClass()->getName()->str() + "<interfacesvtables>";
+ module_->addTypeName(globalName, interfacesArrayTy);
+
+ GlobalVariable* interfacesArray = new GlobalVariable(
+ interfacesArrayTy,
+ true,
+ GlobalVariable::ExternalLinkage,
+ ConstantArray::get(interfacesArrayTy, vtables),
+ globalName,
+ module_);
+
+ return std::make_pair(
+ int(vtables.size())-1,
+ ConstantExpr::getGetElementPtr(
+ interfacesArray,
+ std::vector<llvm::Constant*>(2, ConstantUInt::get(Type::UIntTy, 0))));
+ }
+
+ llvm::Constant* buildClassTypeInfo(ClassFile* cf, const VTableInfo& vi) {
std::vector<llvm::Constant*> typeInfoInit;
- // the depth
- unsigned depth = vi.superVtables.size();
+
+ unsigned depth;
+ llvm::Constant* superClassesVTables;
+ tie(depth, superClassesVTables) = buildSuperClassesVTables(cf, vi);
+
+ // the depth (java/lang/Object has depth 0)
typeInfoInit.push_back(ConstantUInt::get(Type::UIntTy, depth));
- std::vector<llvm::Constant*> vtables;
- for (unsigned i = 0, e = depth; i != e; ++i)
- vtables.push_back(vi.superVtables[i]);
+ // the super classes' vtables
+ typeInfoInit.push_back(superClassesVTables);
- ArrayType* vtablesArrayTy =
- ArrayType::get(superVI.vtable->getType(), depth);
- GlobalVariable* vtablesArray =
- new GlobalVariable(vtablesArrayTy,
- true, GlobalVariable::ExternalLinkage,
- ConstantArray::get(vtablesArrayTy, vtables),
- className + "<supervtables>", module_);
-
- typeInfoInit.push_back(ConstantExpr::getGetElementPtr(
- vtablesArray,
- std::vector<llvm::Constant*>(2, ConstantUInt::get(Type::UIntTy, 0))));
-
- // FIXME: interface lists should go here
- typeInfoInit.push_back(llvm::ConstantSInt::get(Type::IntTy, -1));
- typeInfoInit.push_back(
- llvm::Constant::getNullValue(superVI.vtable->getType()));
-
- return ConstantStruct::get(
- cast<ConstantStruct>(superVI.vtable->getInitializer()->getOperand(0))->getType(),
- typeInfoInit);
+ int lastInterface;
+ llvm::Constant* interfacesVTables;
+ tie(lastInterface, interfacesVTables) = buildInterfacesVTables(cf, vi);
+
+ // the last interface index or the interface index if this is an
+ // interface
+ typeInfoInit.push_back(ConstantSInt::get(Type::IntTy, lastInterface));
+ // the interfaces' vtables
+ typeInfoInit.push_back(interfacesVTables);
+
+ return ConstantStruct::get(VTableInfo::TypeInfoTy, typeInfoInit);
}
const VTableInfo& getVTableInfo(ClassFile* cf) {
- const std::string& className = cf->getThisClass()->getName()->str();
Class2VTableInfoMap::iterator it = c2viMap_.lower_bound(cf);
if (it != c2viMap_.end() && it->first == cf)
return it->second;
+ const std::string& className = cf->getThisClass()->getName()->str();
DEBUG(std::cerr << "Building VTableInfo for: " << className << '\n');
VTableInfo& vi = c2viMap_[cf];
@@ -475,6 +580,7 @@
const VTableInfo& superVI =
getVTableInfo(ClassFile::get(super->getName()->str()));
+ // copy the super vtables array
vi.superVtables.push_back(superVI.vtable);
vi.superVtables.reserve(superVI.superVtables.size() + 1);
std::copy(superVI.superVtables.begin(), superVI.superVtables.end(),
@@ -485,11 +591,13 @@
ConstantStruct* superInit =
cast<ConstantStruct>(superVI.vtable->getInitializer());
std::vector<llvm::Constant*> init(superInit->getNumOperands());
+ // use a null typeinfo struct for now
+ init[0] = llvm::Constant::getNullValue(VTableInfo::TypeInfoTy);
+ // fill in the function pointers as they are in the super
+ // class. overriden methods will be replaced later
for (unsigned i = 0, e = superInit->getNumOperands(); i != e; ++i)
init[i] = superInit->getOperand(i);
vi.m2iMap = superVI.m2iMap;
- // install the new typeinfo block for this class
- init[0] = getClassTypeInfo(cf, vi, superVI);
// add member functions to the vtable
const Methods& methods = cf->getMethods();
@@ -499,14 +607,14 @@
// the contructor is the only non-static method that is not
// dynamically dispatched so we skip it
if (!method->isStatic() && method->getName()->str() != "<init>") {
- std::string methodDescr =
- method->getName()->str() +
- method->getDescriptor()->str();
+ const std::string& methodDescr =
+ method->getName()->str() + method->getDescriptor()->str();
std::string funcName = className + '/' + methodDescr;
+
+ // if this is not an interface we will need to build up the
const FunctionType* funcTy = cast<FunctionType>(
getType(method->getDescriptor(), getClassInfo(cf).type));
-
Function* vfun = module_->getOrInsertFunction(funcName, funcTy);
toCompileFunctions_.insert(vfun);
@@ -519,12 +627,29 @@
}
}
+#ifndef NDEBUG
+ for (unsigned i = 0, e = init.size(); i != e; ++i)
+ assert(init[i] && "No elements in the initializer should be NULL!");
+#endif
+
+ const std::string& globalName = className + "<vtable>";
+
llvm::Constant* vtable = ConstantStruct::get(init);
+ module_->addTypeName(globalName, vtable->getType());
vi.vtable = new GlobalVariable(vtable->getType(),
- true, GlobalVariable::ExternalLinkage,
+ true,
+ GlobalVariable::ExternalLinkage,
vtable,
- className + "<vtable>",
+ globalName,
module_);
+
+ // Now the vtable is complete, install the new typeinfo block
+ // for this class: we install it last because we need the vtable
+ // to exist in order to build it
+ init[0] = buildClassTypeInfo(cf, vi);
+ vi.vtable->setInitializer(ConstantStruct::get(init));
+
+ DEBUG(std::cerr << "Built VTableInfo for: " << className << '\n');
return vi;
}
@@ -730,7 +855,7 @@
// compile all other methods called by this method recursively
for (unsigned i = 0; i != toCompileFunctions_.size(); ++i) {
Function* f = toCompileFunctions_[i];
- compileMethodOnly(f->getName());
+// compileMethodOnly(f->getName());
}
return function;
@@ -1131,24 +1256,31 @@
const ClassInfo& ci = getClassInfo(cf);
const VTableInfo& vi = getVTableInfo(cf);
- std::string methodDescr =
+ const std::string& className = cf->getThisClass()->getName()->str();
+ const 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, cf, LLVM_JAVA_OBJECT_BASE, objRef);
+ Value* objBase = getField(bcI, cf, LLVM_JAVA_OBJECT_BASE, objRef);
+ Function* f = module_->getOrInsertFunction(
+ LLVM_JAVA_GETOBJECTCLASS, PointerType::get(VTableInfo::VTableTy),
+ objBase->getType(), NULL);
+ Value* vtable = new CallInst(f, objBase, TMP, getBBAt(bcI));
vtable = new CastInst(vtable, PointerType::get(vi.vtable->getType()),
TMP, getBBAt(bcI));
- vtable = new LoadInst(vtable, TMP, getBBAt(bcI));
+ vtable = new LoadInst(vtable, className + "<vtable>", 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* vfunPtr = new GetElementPtrInst(vtable, indices, TMP, getBBAt(bcI));
+ Value* vfunPtr =
+ new GetElementPtrInst(vtable, indices, TMP, getBBAt(bcI));
Value* vfun = new LoadInst(vfunPtr, methodDescr, getBBAt(bcI));
+
makeCall(vfun, getBBAt(bcI));
}
@@ -1194,7 +1326,53 @@
}
void do_invokeinterface(unsigned bcI, unsigned index) {
- assert(0 && "not implemented");
+ ConstantMethodRef* methodRef = cf_->getConstantMethodRef(index);
+ ConstantNameAndType* nameAndType = methodRef->getNameAndType();
+
+ ClassFile* cf = ClassFile::get(methodRef->getClass()->getName()->str());
+ const ClassInfo& ci = getClassInfo(cf);
+ const VTableInfo& vi = getVTableInfo(cf);
+
+ const std::string& className = cf->getThisClass()->getName()->str();
+ const 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* objBase = getField(bcI, cf, LLVM_JAVA_OBJECT_BASE, objRef);
+ Function* f = module_->getOrInsertFunction(
+ LLVM_JAVA_GETOBJECTCLASS, PointerType::get(VTableInfo::VTableTy),
+ objBase->getType(), NULL);
+ Value* vtable = new CallInst(f, objBase, TMP, getBBAt(bcI));
+ // get the interfaces array of vtables
+ std::vector<Value*> indices(2, ConstantUInt::get(Type::UIntTy, 0));
+ indices.push_back(ConstantUInt::get(Type::UIntTy, 3));
+ Value* interfaceVTables =
+ new GetElementPtrInst(vtable, indices, TMP, getBBAt(bcI));
+ interfaceVTables = new LoadInst(interfaceVTables, TMP, getBBAt(bcI));
+ // get the actual interface vtable
+ indices.resize(1);
+ indices.push_back(ConstantUInt::get(Type::UIntTy, ci.interfaceIdx));
+ Value* interfaceVTable =
+ new GetElementPtrInst(vtable, indices, TMP, getBBAt(bcI));
+ interfaceVTable =
+ new CastInst(vtable, PointerType::get(VTableInfo::VTableTy),
+ TMP, getBBAt(bcI));
+ interfaceVTable =
+ new LoadInst(interfaceVTable, className + "<vtable>", getBBAt(bcI));
+ // get the function pointer
+ indices.resize(1);
+ 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* vfunPtr =
+ new GetElementPtrInst(interfaceVTable, indices, TMP, getBBAt(bcI));
+ Value* vfun = new LoadInst(vfunPtr, methodDescr, getBBAt(bcI));
+
+ makeCall(vfun, getBBAt(bcI));
}
void do_new(unsigned bcI, unsigned index) {
@@ -1246,11 +1424,9 @@
Value* objRef = opStack_.top(); opStack_.pop();
Value* objBase = getField(bcI, cf, LLVM_JAVA_OBJECT_BASE, objRef);
- Function* f = module_->getOrInsertFunction(LLVM_JAVA_ISINSTANCEOF,
- Type::IntTy,
- objBase->getType(),
- vi.vtable->getType(),
- NULL);
+ Function* f = module_->getOrInsertFunction(
+ LLVM_JAVA_ISINSTANCEOF, Type::IntTy,
+ objBase->getType(), PointerType::get(VTableInfo::VTableTy), NULL);
Value* r = new CallInst(f, objBase, vi.vtable, TMP, getBBAt(bcI));
opStack_.push(r);
}
@@ -1270,6 +1446,10 @@
}
};
+ unsigned CompilerImpl::ClassInfo::InterfaceCount = 0;
+ StructType* CompilerImpl::VTableInfo::VTableTy;
+ StructType* CompilerImpl::VTableInfo::TypeInfoTy;
+
} } } // namespace llvm::Java::
Compiler::Compiler()
More information about the llvm-commits
mailing list