[llvm-commits] CVS: llvm-java/lib/Compiler/Compiler.cpp
Alkis Evlogimenos
alkis at cs.uiuc.edu
Thu Oct 28 13:46:05 PDT 2004
Changes in directory llvm-java/lib/Compiler:
Compiler.cpp updated: 1.132 -> 1.133
---
Log message:
Add array of primitives support.
---
Diffs of the changes: (+295 -11)
Index: llvm-java/lib/Compiler/Compiler.cpp
diff -u llvm-java/lib/Compiler/Compiler.cpp:1.132 llvm-java/lib/Compiler/Compiler.cpp:1.133
--- llvm-java/lib/Compiler/Compiler.cpp:1.132 Thu Oct 28 15:45:12 2004
+++ llvm-java/lib/Compiler/Compiler.cpp Thu Oct 28 15:45:55 2004
@@ -92,6 +92,7 @@
/// object).
struct ClassInfo {
ClassInfo() : type(NULL), interfaceIdx(0) { }
+
Type* type;
unsigned interfaceIdx;
typedef std::map<std::string, unsigned> Field2IndexMap;
@@ -119,6 +120,7 @@
};
typedef std::map<ClassFile*, VTableInfo> Class2VTableInfoMap;
Class2VTableInfoMap c2viMap_;
+ Class2VTableInfoMap ac2viMap_;
public:
Compiler(Module& m)
@@ -389,6 +391,71 @@
return ci;
}
+ /// Creates a ClassInfo object for an array of the specified
+ /// element type.
+ ClassInfo buildArrayClassInfo(Type* elementTy) {
+ ClassInfo arrayInfo;
+
+ std::vector<const Type*> elements;
+ elements.reserve(3);
+ elements.push_back(getClassInfo(ClassFile::get("java/lang/Object")).type);
+ elements.push_back(Type::UIntTy);
+ arrayInfo.f2iMap.insert(std::make_pair("<length>", elements.size()));
+ elements.push_back(ArrayType::get(elementTy, 0));
+ arrayInfo.f2iMap.insert(std::make_pair("<data>", elements.size()));
+
+ arrayInfo.type = StructType::get(elements);
+
+ return arrayInfo;
+ }
+
+ /// Returns the ClassInfo object associated with an array of the
+ /// specified element type.
+ const ClassInfo& getPrimitiveArrayInfo(JType type) {
+ switch (type) {
+ case BOOLEAN: {
+ static ClassInfo arrayInfo = buildArrayClassInfo(Type::BoolTy);
+ return arrayInfo;
+ }
+ case CHAR: {
+ static ClassInfo arrayInfo = buildArrayClassInfo(Type::UShortTy);
+ return arrayInfo;
+ }
+ case FLOAT: {
+ static ClassInfo arrayInfo = buildArrayClassInfo(Type::FloatTy);
+ return arrayInfo;
+ }
+ case DOUBLE: {
+ static ClassInfo arrayInfo = buildArrayClassInfo(Type::DoubleTy);
+ return arrayInfo;
+ }
+ case BYTE: {
+ static ClassInfo arrayInfo = buildArrayClassInfo(Type::SByteTy);
+ return arrayInfo;
+ }
+ case SHORT: {
+ static ClassInfo arrayInfo = buildArrayClassInfo(Type::ShortTy);
+ return arrayInfo;
+ }
+ case INT: {
+ static ClassInfo arrayInfo = buildArrayClassInfo(Type::IntTy);
+ return arrayInfo;
+ }
+ case LONG: {
+ static ClassInfo arrayInfo = buildArrayClassInfo(Type::LongTy);
+ return arrayInfo;
+ }
+ }
+ }
+
+ /// Returns the ClassInfo object associated with an array of the
+ /// specified element type.
+ const ClassInfo& getObjectArrayInfo() {
+ static ClassInfo arrayInfo = buildArrayClassInfo(
+ getClassInfo(ClassFile::get("java/lang/Object")).type);
+ return arrayInfo;
+ }
+
/// Builds the super classes' vtable array for this classfile and
/// its corresponding VTable. The most generic class goes first in
/// the array.
@@ -563,8 +630,8 @@
getVTableInfo(ClassFile::get(super->getName()->str()));
// Copy the super vtables array.
- vi.superVtables.push_back(superVI.vtable);
vi.superVtables.reserve(superVI.superVtables.size() + 1);
+ vi.superVtables.push_back(superVI.vtable);
std::copy(superVI.superVtables.begin(), superVI.superVtables.end(),
std::back_inserter(vi.superVtables));
@@ -594,10 +661,10 @@
std::string funcName = className + '/' + methodDescr;
- const FunctionType* funcTy = cast<FunctionType>(
- getType(method->getDescriptor(), getClassInfo(cf).type));
- Function* vfun = module_.getOrInsertFunction(funcName, funcTy);
- toCompileFunctions_.insert(vfun);
+ const FunctionType* funcTy = cast<FunctionType>(
+ getType(method->getDescriptor(), getClassInfo(cf).type));
+ Function* vfun = module_.getOrInsertFunction(funcName, funcTy);
+ toCompileFunctions_.insert(vfun);
unsigned& index = vi.m2iMap[methodDescr];
if (!index) {
@@ -634,6 +701,138 @@
return vi;
}
+ VTableInfo buildArrayVTableInfo(Type* elementTy) {
+ assert(elementTy->isPrimitiveType() &&
+ "This should not be called for arrays of non-primitive types");
+
+ VTableInfo vi;
+ const VTableInfo& superVI =
+ getVTableInfo(ClassFile::get("java/lang/Object"));
+
+ // Add java/lang/Object as its superclass.
+ vi.superVtables.reserve(1);
+ vi.superVtables.push_back(superVI.vtable);
+
+ // Copy the constants from java/lang/Object vtable.
+ 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;
+
+#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 =
+ elementTy->getDescription() + "<vtable>";
+
+ llvm::Constant* vtable = ConstantStruct::get(init);
+ module_.addTypeName(globalName, vtable->getType());
+ vi.vtable = new GlobalVariable(vtable->getType(),
+ true,
+ GlobalVariable::ExternalLinkage,
+ vtable,
+ globalName,
+ &module_);
+
+ // Construct the typeinfo now.
+ std::vector<llvm::Constant*> typeInfoInit;
+ typeInfoInit.push_back(ConstantSInt::get(Type::IntTy, 1));
+ // Build the super classes' vtable array.
+ ArrayType* vtablesArrayTy =
+ ArrayType::get(PointerType::get(VTableInfo::VTableTy),
+ vi.superVtables.size());
+
+ GlobalVariable* vtablesArray = new GlobalVariable(
+ vtablesArrayTy,
+ true,
+ GlobalVariable::ExternalLinkage,
+ ConstantArray::get(vtablesArrayTy, vi.superVtables),
+ elementTy->getDescription() + "<superclassesvtables>",
+ &module_);
+
+ typeInfoInit.push_back(
+ ConstantExpr::getGetElementPtr(
+ vtablesArray,
+ std::vector<llvm::Constant*>(2, ConstantUInt::get(Type::UIntTy, 0))));
+ typeInfoInit.push_back(ConstantSInt::get(Type::IntTy, 0));
+ typeInfoInit.push_back(
+ llvm::Constant::getNullValue(
+ PointerType::get(PointerType::get(VTableInfo::VTableTy))));
+
+ init[0] = ConstantStruct::get(VTableInfo::TypeInfoTy, typeInfoInit);
+ vi.vtable->setInitializer(ConstantStruct::get(init));
+
+ return vi;
+ }
+
+ // Returns the VTableInfo object for an array of the specified
+ // element type.
+ const VTableInfo& getPrimitiveArrayVTableInfo(JType type) {
+ switch (type) {
+ case BOOLEAN: {
+ static VTableInfo arrayInfo = buildArrayVTableInfo(Type::BoolTy);
+ return arrayInfo;
+ }
+ case CHAR: {
+ static VTableInfo arrayInfo = buildArrayVTableInfo(Type::UShortTy);
+ return arrayInfo;
+ }
+ case FLOAT: {
+ static VTableInfo arrayInfo = buildArrayVTableInfo(Type::FloatTy);
+ return arrayInfo;
+ }
+ case DOUBLE: {
+ static VTableInfo arrayInfo = buildArrayVTableInfo(Type::DoubleTy);
+ return arrayInfo;
+ }
+ case BYTE: {
+ static VTableInfo arrayInfo = buildArrayVTableInfo(Type::SByteTy);
+ return arrayInfo;
+ }
+ case SHORT: {
+ static VTableInfo arrayInfo = buildArrayVTableInfo(Type::ShortTy);
+ return arrayInfo;
+ }
+ case INT: {
+ static VTableInfo arrayInfo = buildArrayVTableInfo(Type::IntTy);
+ return arrayInfo;
+ }
+ case LONG: {
+ static VTableInfo arrayInfo = buildArrayVTableInfo(Type::LongTy);
+ return arrayInfo;
+ }
+ }
+ }
+
+// const VTableInfo& getArrayVTableInfo(ClassFile* cf) {
+// Class2VTableInfoMap::iterator it = ac2viMap_.lower_bound(cf);
+// if (it != ac2viMap_.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 = ac2viMap_[cf];
+
+// assert(!vi.vtable && vi.m2iMap.empty() &&
+// "got already initialized VTableInfo!");
+
+
+// ConstantClass* super = cf->getSuperClass();
+// if (!super) {
+// }
+// else {
+
+// }
+// }
+
/// Emits the necessary code to get a pointer to a static field of
/// an object.
GlobalVariable* getStaticField(unsigned index) {
@@ -780,7 +979,7 @@
}
DEBUG(std::cerr << "Finished compilation of method: "
- << classMethodDesc << '\n');
+ << classMethodDesc << '\n');
DEBUG(function->dump());
return function;
@@ -953,7 +1152,17 @@
void do_saload() { do_aload_common(); }
void do_aload_common() {
- assert(0 && "not implemented");
+ Value* index = currentOpStack_->pop(currentBB_);
+ Value* arrayRef = currentOpStack_->pop(currentBB_);
+
+ std::vector<Value*> indices;
+ indices.reserve(2);
+ indices.push_back(ConstantUInt::get(Type::UIntTy, 2));
+ indices.push_back(index);
+ Value* elementPtr =
+ new GetElementPtrInst(arrayRef, indices, TMP, currentBB_);
+ Value* result = new LoadInst(elementPtr, TMP, currentBB_);
+ currentOpStack_->push(result, currentBB_);
}
void do_istore(unsigned index) { do_store_common(index); }
@@ -977,7 +1186,22 @@
void do_sastore() { do_astore_common(); }
void do_astore_common() {
- assert(0 && "not implemented");
+ Value* value = currentOpStack_->pop(currentBB_);
+ Value* index = currentOpStack_->pop(currentBB_);
+ Value* arrayRef = currentOpStack_->pop(currentBB_);
+
+ std::vector<Value*> indices;
+ indices.reserve(2);
+ indices.push_back(ConstantUInt::get(Type::UIntTy, 2));
+ indices.push_back(index);
+ Value* elementPtr =
+ new GetElementPtrInst(arrayRef, indices, TMP, currentBB_);
+ // We need this case because ints on the stack can be stored to
+ // arrays of bool, byte, short or char.
+ value = new CastInst(
+ value, cast<PointerType>(elementPtr->getType())->getElementType(),
+ TMP, currentBB_);
+ new StoreInst(value, elementPtr, currentBB_);
}
void do_pop() {
@@ -1184,6 +1408,8 @@
void do_iinc(unsigned index, int amount) {
Value* v = currentLocals_->load(index, currentBB_);
Value* a = ConstantSInt::get(Type::IntTy, amount);
+ std::cerr << "v: " << *v << '\n';
+ std::cerr << "a: " << *a << '\n';
BinaryOperator::createAdd(v, a, TMP, currentBB_);
currentLocals_->store(index, v, currentBB_);
}
@@ -1381,6 +1607,9 @@
void do_putfield(unsigned index) {
Value* v = currentOpStack_->pop(currentBB_);
Value* p = currentOpStack_->pop(currentBB_);
+ Value* fp = getField(index, p);
+ const Type* ft = cast<PointerType>(fp->getType())->getElementType();
+ v = new CastInst(v, ft, TMP, currentBB_);
new StoreInst(v, getField(index, p), currentBB_);
}
@@ -1464,7 +1693,7 @@
const ClassInfo& ci = getClassInfo(ClassFile::get(className));
FunctionType* funcTy =
- cast<FunctionType>(getType(nameAndType->getDescriptor(), ci.type));
+ cast<FunctionType>(getType(nameAndType->getDescriptor(), ci.type));
Function* function = module_.getOrInsertFunction(funcName, funcTy);
toCompileFunctions_.insert(function);
makeCall(function, getParams(funcTy));
@@ -1561,8 +1790,56 @@
currentOpStack_->push(objRef, currentBB_);
}
+ Value* getArrayLengthPtr(Value* arrayRef) const {
+ std::vector<Value*> indices;
+ indices.reserve(2);
+ indices.push_back(ConstantUInt::get(Type::UIntTy, 0));
+ indices.push_back(ConstantUInt::get(Type::UIntTy, 1));
+
+ return new GetElementPtrInst(arrayRef, indices, TMP, currentBB_);
+ }
+
+ Value* getArrayObjectBasePtr(Value* arrayRef) const {
+ std::vector<Value*> indices;
+ indices.reserve(2);
+ indices.push_back(ConstantUInt::get(Type::UIntTy, 0));
+ indices.push_back(ConstantUInt::get(Type::UIntTy, 0));
+
+ return new GetElementPtrInst(arrayRef, indices, TMP, currentBB_);
+ }
+
void do_newarray(JType type) {
- assert(0 && "not implemented");
+ Value* count = currentOpStack_->pop(currentBB_);
+ count = new CastInst(count, Type::UIntTy, TMP, currentBB_);
+
+ const ClassInfo& ci = getPrimitiveArrayInfo(type);
+ const VTableInfo& vi = getPrimitiveArrayVTableInfo(type);
+
+ // The size of the array part of the struct.
+ Value* size = BinaryOperator::create(
+ Instruction::Mul, count, ConstantExpr::getSizeOf(getType(type)),
+ TMP, currentBB_);
+ // Plus the size of the rest of the struct.
+ size = BinaryOperator::create(
+ Instruction::Add, size, ConstantExpr::getSizeOf(ci.type),
+ TMP, currentBB_);
+ // Allocate memory for the object.
+ Value* objRef = new MallocInst(Type::SByteTy, size, TMP, currentBB_);
+ objRef = new CastInst(objRef, PointerType::get(ci.type), TMP, currentBB_);
+
+ // Store the size.
+ Value* lengthPtr = getArrayLengthPtr(objRef);
+ new StoreInst(count, lengthPtr, currentBB_);
+ // Install the vtable pointer.
+ Value* objBase = getArrayObjectBasePtr(objRef);
+ Value* vtable = new CastInst(vi.vtable,
+ PointerType::get(VTableInfo::VTableTy),
+ TMP, currentBB_);
+ Function* f = module_.getOrInsertFunction(
+ LLVM_JAVA_SETOBJECTCLASS, Type::VoidTy,
+ objBase->getType(), PointerType::get(VTableInfo::VTableTy), NULL);
+ new CallInst(f, objBase, vtable, "", currentBB_);
+ currentOpStack_->push(objRef, currentBB_);
}
void do_anewarray(unsigned index) {
@@ -1570,7 +1847,14 @@
}
void do_arraylength() {
- assert(0 && "not implemented");
+ Value* arrayRef = currentOpStack_->pop(currentBB_);
+ const ClassInfo& ci = getObjectArrayInfo();
+ arrayRef =
+ new CastInst(arrayRef, PointerType::get(ci.type), TMP, currentBB_);
+ Value* lengthPtr = getArrayLengthPtr(arrayRef);
+ Value* length = new LoadInst(lengthPtr, TMP, currentBB_);
+ length = new CastInst(length, Type::IntTy, TMP, currentBB_);
+ currentOpStack_->push(length, currentBB_);
}
void do_athrow() {
More information about the llvm-commits
mailing list