[llvm-commits] CVS: llvm-java/lib/Compiler/Compiler.cpp
Alkis Evlogimenos
alkis at cs.uiuc.edu
Mon Sep 13 12:54:22 PDT 2004
Changes in directory llvm-java/lib/Compiler:
Compiler.cpp updated: 1.93 -> 1.94
---
Log message:
Modify the vtable struct to reflect the object-layout doc.
---
Diffs of the changes: (+252 -81)
Index: llvm-java/lib/Compiler/Compiler.cpp
diff -u llvm-java/lib/Compiler/Compiler.cpp:1.93 llvm-java/lib/Compiler/Compiler.cpp:1.94
--- llvm-java/lib/Compiler/Compiler.cpp:1.93 Wed Sep 1 23:52:13 2004
+++ llvm-java/lib/Compiler/Compiler.cpp Mon Sep 13 14:54:11 2004
@@ -30,6 +30,15 @@
#include <stack>
#include <vector>
+#define LLVM_JAVA_OBJECT_BASE "struct.llvm_java_object_base"
+#define LLVM_JAVA_OBJECT_HEADER "struct.llvm_java_object_header"
+#define LLVM_JAVA_OBJECT_TYPEINFO "struct.llvm_java_object_typeinfo"
+#define LLVM_JAVA_OBJECT_VTABLE "struct.llvm_java_object_vtable"
+
+#define LLVM_JAVA_STATIC_INIT "llvm_java_static_init"
+
+#define LLVM_JAVA_ISINSTANCEOF "llvm_java_IsInstanceOf"
+
using namespace llvm;
using namespace llvm::Java;
@@ -135,6 +144,7 @@
struct VTableInfo {
VTableInfo() : vtable(NULL) { }
GlobalVariable* vtable;
+ std::vector<GlobalVariable*> superVtables;
typedef std::map<std::string, unsigned> Method2IndexMap;
Method2IndexMap m2iMap;
};
@@ -237,6 +247,135 @@
}
}
+ void initializeClassInfoMap() {
+ DEBUG(std::cerr << "Building ClassInfo for: java/lang/Object\n");
+ ClassFile* cf = ClassFile::getClassFile("java/lang/Object");
+ ClassInfo& ci = c2ciMap_["java/lang/Object"];
+ assert(!ci.type && ci.f2iMap.empty() &&
+ "java/lang/Object ClassInfo should not be initialized!");
+ ci.type = OpaqueType::get();
+
+ std::vector<const Type*> elements;
+
+ // because this is java/lang/Object, we add the opaque
+ // llvm_java_object_base type first
+ Type* base = OpaqueType::get();
+ module_->addTypeName(LLVM_JAVA_OBJECT_BASE, base);
+ ci.f2iMap.insert(std::make_pair(LLVM_JAVA_OBJECT_BASE, elements.size()));
+ elements.push_back(base);
+
+ const Fields& fields = cf->getFields();
+ for (unsigned i = 0, e = fields.size(); i != e; ++i) {
+ Field* field = fields[i];
+ if (!field->isStatic()) {
+ ci.f2iMap.insert(
+ std::make_pair(field->getName()->str(), elements.size()));
+ elements.push_back(getType(field->getDescriptor()));
+ }
+ }
+ PATypeHolder holder = ci.type;
+ cast<OpaqueType>(ci.type)->refineAbstractTypeTo(StructType::get(elements));
+ ci.type = holder.get();
+ DEBUG(std::cerr << "Adding java/lang/Object = "
+ << *ci.type << " to type map\n");
+ module_->addTypeName("java/lang/Object", ci.type);
+
+ assert(ci.type && "ClassInfo not initialized properly!");
+ emitStaticInitializers(cf);
+ }
+
+ void initializeVTableInfoMap() {
+ DEBUG(std::cerr << "Building VTableInfo for: java/lang/Object\n");
+ ClassFile* cf = ClassFile::getClassFile("java/lang/Object");
+ VTableInfo& vi = c2viMap_["java/lang/Object"];
+ assert(!vi.vtable && vi.m2iMap.empty() &&
+ "java/lang/Object VTableInfo should not be initialized!");
+
+ Type* VTtype = OpaqueType::get();
+
+ std::vector<const Type*> elements;
+ std::vector<llvm::Constant*> init;
+
+ // this is java/lang/Object so we must add a
+ // llvm_java_object_typeinfo struct first
+
+ // depth
+ elements.push_back(Type::UIntTy);
+ init.push_back(llvm::ConstantUInt::get(elements[0], 0));
+ // superclasses vtable pointers
+ elements.push_back(PointerType::get(PointerType::get(VTtype)));
+ init.push_back(llvm::Constant::getNullValue(elements[1]));
+ // last interface index
+ elements.push_back(Type::IntTy);
+ init.push_back(llvm::ConstantSInt::get(elements[2], -1));
+ // interfaces vtable pointers
+ 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);
+
+ // now that we have both the type and initializer for the
+ // llvm_java_object_typeinfo struct we can start adding the
+ // function pointers
+ elements.clear();
+ init.clear();
+
+ /// first add the typeinfo struct itself
+ elements.push_back(typeInfoInit->getType());
+ // add the typeinfo block for this class
+ init.push_back(typeInfoInit);
+
+ const Methods& methods = cf->getMethods();
+
+ // add member functions to the vtable
+ for (unsigned i = 0, e = methods.size(); i != e; ++i) {
+ Method* method = methods[i];
+ // 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();
+
+ std::string funcName = "java/lang/Object/" + methodDescr;
+ const FunctionType* funcTy = cast<FunctionType>(
+ getType(method->getDescriptor(),
+ getClassInfo("java/lang/Object").type));
+
+ Function* vfun = module_->getOrInsertFunction(funcName, funcTy);
+ toCompileFunctions_.insert(vfun);
+
+ unsigned& index = vi.m2iMap[methodDescr];
+ if (!index) {
+ index = elements.size();
+ elements.resize(index + 1, NULL);
+ init.resize(index + 1, NULL);
+ }
+ elements[index] = vfun->getType();
+ init[index] = vfun;
+ }
+ }
+
+ PATypeHolder holder = VTtype;
+ cast<OpaqueType>(VTtype)->refineAbstractTypeTo(StructType::get(elements));
+ VTtype = cast<StructType>(holder.get());
+
+ vi.vtable = new GlobalVariable(VTtype,
+ 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
+ }
+
+ void initializeTypeMaps() {
+ initializeClassInfoMap();
+ initializeVTableInfoMap();
+ }
+
const ClassInfo& getClassInfo(const std::string& className) {
Class2ClassInfoMap::iterator it = c2ciMap_.lower_bound(className);
if (it != c2ciMap_.end() && it->first == className)
@@ -251,25 +390,16 @@
std::vector<const Type*> elements;
ConstantClass* super = cf->getSuperClass();
- const ClassInfo* superCI =
- super ? &getClassInfo(super->getName()->str()) : NULL;
- if (superCI)
- elements.push_back(superCI->type);
- else {
- // 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);
- ci.f2iMap.insert(std::make_pair("<llvm_java_base>", elements.size()));
- elements.push_back(base);
- }
+ assert(super && "Class does not have superclass!");
+ const ClassInfo& superCI = getClassInfo(super->getName()->str());
+ elements.push_back(superCI.type);
const Fields& fields = cf->getFields();
for (unsigned i = 0, e = fields.size(); i != e; ++i) {
Field* field = fields[i];
if (!field->isStatic()) {
- ci.f2iMap.insert(std::make_pair(field->getName()->str(),
- elements.size()));
+ ci.f2iMap.insert(
+ std::make_pair(field->getName()->str(), elements.size()));
elements.push_back(getType(field->getDescriptor()));
}
}
@@ -285,6 +415,43 @@
return ci;
}
+ llvm::Constant* getClassTypeInfo(const std::string& className,
+ 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
+
+ std::vector<llvm::Constant*> typeInfoInit;
+ // the depth
+ unsigned depth = vi.superVtables.size();
+ 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]);
+
+ 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);
+ }
+
const VTableInfo& getVTableInfo(const std::string& className) {
Class2VTableInfoMap::iterator it = c2viMap_.lower_bound(className);
if (it != c2viMap_.end() && it->first == className)
@@ -299,65 +466,65 @@
std::vector<const Type*> elements;
std::vector<llvm::Constant*> init;
ConstantClass* super = cf->getSuperClass();
- const VTableInfo* superVI =
- super ? &getVTableInfo(super->getName()->str()) : NULL;
+ assert(super && "Class does not have superclass!");
+ const VTableInfo& superVI = getVTableInfo(super->getName()->str());
- 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();
-
- std::string funcName = className + '/' + methodDescr;
- const FunctionType* funcTy = cast<FunctionType>(
- getType(method->getDescriptor(), getClassInfo(className).type));
-
- Function* vfun = module_->getOrInsertFunction(funcName, funcTy);
- toCompileFunctions_.insert(vfun);
-
- unsigned& index = vi.m2iMap[methodDescr];
- if (!index) {
- index = elements.size();
- elements.resize(index + 1, NULL);
- init.resize(index + 1, NULL);
- }
- elements[index] = vfun->getType();
- init[index] = vfun;
+ vi.superVtables.push_back(superVI.vtable);
+ vi.superVtables.reserve(superVI.superVtables.size() + 1);
+ std::copy(superVI.superVtables.begin(), superVI.superVtables.end(),
+ std::back_inserter(vi.superVtables));
+
+ // 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;
+ // install the new typeinfo block for this class
+ init[0] = getClassTypeInfo(className, vi, superVI);
+
+ // add member functions to the vtable
+ const Methods& methods = cf->getMethods();
+ init.resize(elements.size(), NULL);
+
+ for (unsigned i = 0, e = methods.size(); i != e; ++i) {
+ Method* method = methods[i];
+ // 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();
+
+ std::string funcName = className + '/' + methodDescr;
+ const FunctionType* funcTy = cast<FunctionType>(
+ getType(method->getDescriptor(), getClassInfo(className).type));
+
+ Function* vfun = module_->getOrInsertFunction(funcName, funcTy);
+ toCompileFunctions_.insert(vfun);
+
+ unsigned& index = vi.m2iMap[methodDescr];
+ if (!index) {
+ index = elements.size();
+ elements.resize(index + 1, NULL);
+ init.resize(index + 1, NULL);
}
+ elements[index] = vfun->getType();
+ init[index] = vfun;
}
+ }
- vi.vtable = new GlobalVariable(StructType::get(elements),
- true, GlobalVariable::ExternalLinkage,
- ConstantStruct::get(init),
- className + "<vtable>",
- module_);
- return vi;
+ vi.vtable = new GlobalVariable(StructType::get(elements),
+ true, GlobalVariable::ExternalLinkage,
+ ConstantStruct::get(init),
+ className + "<vtable>",
+ module_);
+ return vi;
}
Value* getOrCreateLocal(unsigned index, Type* type) {
@@ -489,7 +656,7 @@
name += method->getName()->str();
name += method->getDescriptor()->str();
- Function* hook = module_->getOrInsertFunction("llvm_java_static_init",
+ Function* hook = module_->getOrInsertFunction(LLVM_JAVA_STATIC_INIT,
Type::VoidTy, 0);
Function* init = module_->getOrInsertFunction(name, Type::VoidTy, 0);
@@ -499,7 +666,7 @@
// llvm_java_static_init
if (toCompileFunctions_.insert(init)) {
assert(hook->front().getTerminator() &&
- "llvm_java_static_init should have a terminator!");
+ LLVM_JAVA_STATIC_INIT " should have a terminator!");
new CallInst(init, "", hook->front().getTerminator());
// we also create the global variables of this class
const Fields& fields = classfile->getFields();
@@ -507,8 +674,7 @@
Field* field = fields[i];
if (field->isStatic()) {
llvm::Constant* init = NULL;
- if (ConstantValueAttribute* cv =
- field->getConstantValueAttribute())
+ if (ConstantValueAttribute* cv = field->getConstantValueAttribute())
init = getConstant(cv->getValue());
std::string globalName =
@@ -549,13 +715,17 @@
Function* compileMethod(Module& module,
const std::string& classMethodDesc) {
module_ = &module;
+
// initialize the static initializer function
Function* staticInit =
- module_->getOrInsertFunction("llvm_java_static_init",
+ module_->getOrInsertFunction(LLVM_JAVA_STATIC_INIT,
Type::VoidTy, 0);
BasicBlock* staticInitBB = new BasicBlock("entry", staticInit);
new ReturnInst(NULL, staticInitBB);
+ // initialize type maps and globals (vtables)
+ initializeTypeMaps();
+
// compile the method requested
Function* function = compileMethodOnly(classMethodDesc);
// compile all other methods called by this method recursively
@@ -969,7 +1139,7 @@
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);
+ Value* vtable = getField(bcI, className, LLVM_JAVA_OBJECT_BASE, objRef);
vtable = new CastInst(vtable, PointerType::get(vi.vtable->getType()),
TMP, getBBAt(bcI));
vtable = new LoadInst(vtable, TMP, getBBAt(bcI));
@@ -1038,7 +1208,7 @@
Value* objRef = new MallocInst(ci.type,
ConstantUInt::get(Type::UIntTy, 0),
TMP, getBBAt(bcI));
- Value* vtable = getField(bcI, className, "<llvm_java_base>", objRef);
+ Value* vtable = getField(bcI, className, LLVM_JAVA_OBJECT_BASE, objRef);
vtable = new CastInst(vtable, PointerType::get(vi.vtable->getType()),
TMP, getBBAt(bcI));
vtable = new StoreInst(vi.vtable, vtable, getBBAt(bcI));
@@ -1077,12 +1247,13 @@
const VTableInfo& vi = getVTableInfo(className);
Value* objRef = opStack_.top(); opStack_.pop();
- Value* vtable = getField(bcI, className, "<llvm_java_base>", objRef);
- Function* f = module_->getOrInsertFunction("<llvm_java_instanceof>",
+ Value* objBase = getField(bcI, className, LLVM_JAVA_OBJECT_BASE, objRef);
+ Function* f = module_->getOrInsertFunction(LLVM_JAVA_ISINSTANCEOF,
Type::IntTy,
- vtable->getType(),
- vtable->getType(), NULL);
- Value* r = new CallInst(f, vtable, vi.vtable, TMP, getBBAt(bcI));
+ objBase->getType(),
+ vi.vtable->getType(),
+ NULL);
+ Value* r = new CallInst(f, objBase, vi.vtable, TMP, getBBAt(bcI));
opStack_.push(r);
}
More information about the llvm-commits
mailing list