| //===-- VMClass.cpp - Compiler representation of a Java class ---*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file was developed by the LLVM research group and is distributed under |
| // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file contains the declaration of the Class class that represents a |
| // compile time representation of a Java class (java.lang.Class). This unlike |
| // a classfile representation, it resolves the constant pool, creates global |
| // variables for the static members of this class and also creates the class |
| // record (vtable) of this class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #define DEBUG_TYPE "javaclass" |
| |
| #include "VMClass.h" |
| #include "Resolver.h" |
| #include <llvm/DerivedTypes.h> |
| #include <llvm/Constants.h> |
| #include <llvm/Java/ClassFile.h> |
| #include <llvm/Support/Debug.h> |
| |
| using namespace llvm; |
| using namespace llvm::Java; |
| |
| // On initialization we create a placeholder global for the class |
| // record that will be patched later when the class record is |
| // computed. |
| void VMClass::init() |
| { |
| classRecord_ = new GlobalVariable( |
| OpaqueType::get(), |
| false, |
| GlobalVariable::ExternalLinkage, |
| NULL, |
| getName() + "<class_record>", |
| resolver_->getModule()); |
| } |
| |
| VMClass::VMClass(Resolver* resolver, const std::string& className) |
| : name_(className), |
| descriptor_(Resolver::canonicalizeClassName(className)), |
| resolver_(resolver), |
| classFile_(ClassFile::get(className)), |
| componentClass_(NULL), |
| layoutType_(OpaqueType::get()), |
| type_(PointerType::get(layoutType_)), |
| interfaceIndex_(INVALID_INTERFACE_INDEX), |
| resolvedConstantPool_(classFile_->getNumConstants()) |
| { |
| init(); |
| } |
| |
| VMClass::VMClass(Resolver* resolver, const VMClass* componentClass) |
| : name_('[' + componentClass->getDescriptor()), |
| descriptor_(name_), |
| resolver_(resolver), |
| classFile_(NULL), |
| componentClass_(componentClass), |
| layoutType_(OpaqueType::get()), |
| type_(PointerType::get(layoutType_)), |
| interfaceIndex_(INVALID_INTERFACE_INDEX) |
| { |
| init(); |
| } |
| |
| VMClass::VMClass(Resolver* resolver, const Type* type) |
| : name_(type == Type::SByteTy ? "byte" : |
| type == Type::UShortTy ? "char" : |
| type == Type::DoubleTy ? "double" : |
| type == Type::FloatTy ? "float" : |
| type == Type::IntTy ? "int" : |
| type == Type::LongTy ? "long" : |
| type == Type::ShortTy ? "short" : |
| type == Type::BoolTy ? "boolean" : "void"), |
| descriptor_(type == Type::SByteTy ? "B" : |
| type == Type::UShortTy ? "C" : |
| type == Type::DoubleTy ? "D" : |
| type == Type::FloatTy ? "F" : |
| type == Type::IntTy ? "I" : |
| type == Type::LongTy ? "J" : |
| type == Type::ShortTy ? "S" : |
| type == Type::BoolTy ? "Z" : "V"), |
| resolver_(resolver), |
| classFile_(NULL), |
| componentClass_(NULL), |
| layoutType_(const_cast<Type*>(type)), |
| type_(type), |
| interfaceIndex_(INVALID_INTERFACE_INDEX) |
| { |
| init(); |
| } |
| |
| const VMField* VMClass::lookupField(const std::string& name) const |
| { |
| if (const VMField* field = getField(name)) |
| return field; |
| |
| for (unsigned i = 0, e = getNumInterfaces(); i != e; ++i) { |
| const VMClass* interface = getInterface(i); |
| if (const VMField* field = interface->getField(name)) |
| return field; |
| } |
| |
| for (unsigned i = 0, e = getNumSuperClasses(); i != e; ++i) { |
| const VMClass* superClass = getSuperClass(i); |
| if (const VMField* field = superClass->getField(name)) |
| return field; |
| } |
| |
| return NULL; |
| } |
| |
| const VMMethod* VMClass::lookupMethod(const std::string& nameAndType) const |
| { |
| if (const VMMethod* method = getMethod(nameAndType)) |
| return method; |
| |
| if (isInterface()) |
| for (unsigned i = 0, e = getNumInterfaces(); i != e; ++i) { |
| const VMClass* interface = getInterface(i); |
| if (const VMMethod* method = interface->getMethod(nameAndType)) |
| return method; |
| } |
| else |
| for (unsigned i = 0, e = getNumSuperClasses(); i != e; ++i) { |
| const VMClass* superClass = getSuperClass(i); |
| if (const VMMethod* method = superClass->getMethod(nameAndType)) |
| return method; |
| } |
| |
| return NULL; |
| } |
| |
| void VMClass::computeLayout() |
| { |
| DEBUG(std::cerr << "Computing layout for: " << getName() << '\n'); |
| // The layout of primitive classes is already computed. |
| if (isPrimitive()) { |
| DEBUG(std::cerr << "Computed layout for: " << getName() << '\n'); |
| return; |
| } |
| |
| std::vector<const Type*> layout; |
| if (isArray()) { |
| layout.reserve(3); |
| layout.push_back(resolver_->getClass("java/lang/Object")->getLayoutType()); |
| layout.push_back(Type::UIntTy); |
| layout.push_back(ArrayType::get(componentClass_->getType(), 0)); |
| } |
| else { |
| if (const VMClass* superClass = getSuperClass()) |
| layout.push_back(superClass->getLayoutType()); |
| else // This is java/lang/Object |
| layout.push_back(resolver_->getObjectBaseLayoutType()); |
| // Now add the fields. |
| const Fields& fields = classFile_->getFields(); |
| for (unsigned i = 0, e = fields.size(); i != e; ++i) { |
| Field* field = fields[i]; |
| const std::string& name = field->getName()->str(); |
| if (field->isStatic()) { |
| FieldMap::iterator i = fieldMap_.insert( |
| std::make_pair(name, VMField(this, field))).first; |
| staticFields_.push_back(&i->second); |
| } |
| else { |
| unsigned index = memberFields_.size() + 1; |
| FieldMap::iterator i = fieldMap_.insert( |
| std::make_pair(name, VMField(this, field, index))).first; |
| const VMField* vmf = &i->second; |
| memberFields_.push_back(vmf); |
| layout.push_back(vmf->getClass()->getType()); |
| } |
| } |
| } |
| |
| PATypeHolder holder = layoutType_; |
| Type* resolvedType = StructType::get(layout); |
| cast<OpaqueType>(layoutType_)->refineAbstractTypeTo(resolvedType); |
| layoutType_ = holder.get(); |
| type_ = PointerType::get(layoutType_); |
| |
| DEBUG(std::cerr << "Computed layout for: " << getName() << '\n'); |
| } |
| |
| llvm::Constant* VMClass::buildSuperClassRecords() const |
| { |
| std::vector<llvm::Constant*> init; |
| init.reserve(getNumSuperClasses()); |
| for (unsigned i = getNumSuperClasses(); i--; ) |
| init.push_back(ConstantExpr::getCast( |
| getSuperClass(i)->getClassRecord(), |
| resolver_->getClassRecordPtrType())); |
| |
| const ArrayType* superClassRecordsType = |
| ArrayType::get(resolver_->getClassRecordPtrType(), init.size()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| superClassRecordsType, |
| true, |
| GlobalVariable::ExternalLinkage, |
| ConstantArray::get(superClassRecordsType, init), |
| getName() + "<super_class_records>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* |
| VMClass::buildInterfaceClassRecord(const VMClass* interface) const |
| { |
| assert(interface->isInterface() && "Must be passed an interface!"); |
| |
| std::vector<llvm::Constant*> init; |
| init.reserve(interface->getNumDynamicMethods() + 1); |
| // Insert a null type info for this interface. |
| init.push_back(llvm::Constant::getNullValue(resolver_->getTypeInfoType())); |
| // For each method this interface declares, find the corresponding |
| // method in this class and put it in its slot. |
| for (unsigned i = 0, e = interface->getNumDynamicMethods(); i != e; ++i) { |
| assert(init.size() == i+1 && "Interface method not found in class!"); |
| const VMMethod* interfaceMethod = interface->getDynamicMethod(i); |
| for (unsigned j = 0, f = getNumDynamicMethods(); j != f; ++j) { |
| const VMMethod* method = getDynamicMethod(j); |
| if (method->getName() == interfaceMethod->getName() && |
| method->getDescriptor() == interfaceMethod->getDescriptor()) { |
| init.push_back(method->getFunction()); |
| break; |
| } |
| } |
| } |
| |
| llvm::Constant* classRecordInit = ConstantStruct::get(init); |
| |
| return ConstantExpr::getCast( |
| new GlobalVariable( |
| classRecordInit->getType(), |
| true, |
| GlobalVariable::ExternalLinkage, |
| classRecordInit, |
| getName() + '+' + interface->getName() + "<class_record>", |
| resolver_->getModule()), |
| resolver_->getClassRecordPtrType()); |
| } |
| |
| llvm::Constant* VMClass::buildInterfaceClassRecords() const |
| { |
| // This is an interface or primitive class record so it doesn't |
| // implement any interfaces. Thus the pointer to the array of |
| // implemented interfaces is null. |
| if (isInterface() || isPrimitive()) { |
| const Type* classRecordPtrPtrType = |
| PointerType::get(resolver_->getClassRecordPtrType()); |
| |
| return llvm::Constant::getNullValue(classRecordPtrPtrType); |
| } |
| |
| // Otherwise this is a class or array class record so we have to |
| // fill in the array of implemented interfaces up the max interface |
| // index and build each individual interface class record for this |
| // class. |
| llvm::Constant* nullClassRecord = |
| llvm::Constant::getNullValue(resolver_->getClassRecordPtrType()); |
| std::vector<llvm::Constant*> init(getInterfaceIndex()+1, nullClassRecord); |
| |
| for (unsigned i = 0, e = getNumInterfaces(); i != e; ++i) { |
| const VMClass* interface = getInterface(i); |
| init[interface->getInterfaceIndex()] = buildInterfaceClassRecord(interface); |
| } |
| |
| const ArrayType* interfaceClassRecordsType = |
| ArrayType::get(resolver_->getClassRecordPtrType(), init.size()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| interfaceClassRecordsType, |
| true, |
| GlobalVariable::ExternalLinkage, |
| ConstantArray::get(interfaceClassRecordsType, init), |
| getName() + "<interface_class_records>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* VMClass::buildClassName() const |
| { |
| llvm::Constant* name = ConstantArray::get(getName()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| name->getType(), |
| true, |
| GlobalVariable::ExternalLinkage, |
| name, |
| getName() + "<classname>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* VMClass::buildFieldDescriptors() const |
| { |
| std::vector<llvm::Constant*> init; |
| init.reserve(memberFields_.size()+1); |
| |
| for (unsigned i = 0, e = memberFields_.size(); i != e; ++i) { |
| const VMField* field = memberFields_[i]; |
| init.push_back(field->buildFieldDescriptor()); |
| } |
| // Null terminate. |
| init.push_back(llvm::Constant::getNullValue(PointerType::get(Type::SByteTy))); |
| |
| const ArrayType* arrayType = |
| ArrayType::get(init.back()->getType(), init.size()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| arrayType, |
| true, |
| GlobalVariable::ExternalLinkage, |
| ConstantArray::get(arrayType, init), |
| getName() + "<field_descriptors>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* VMClass::buildFieldOffsets() const |
| { |
| std::vector<llvm::Constant*> init; |
| init.reserve(memberFields_.size()); |
| |
| for (unsigned i = 0, e = memberFields_.size(); i != e; ++i) { |
| const VMField* field = memberFields_[i]; |
| init.push_back(field->buildFieldOffset()); |
| } |
| |
| const ArrayType* arrayType = ArrayType::get(Type::UIntTy, init.size()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| arrayType, |
| true, |
| GlobalVariable::ExternalLinkage, |
| ConstantArray::get(arrayType, init), |
| getName() + "<field_offsets>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* VMClass::buildStaticFieldDescriptors() const |
| { |
| std::vector<llvm::Constant*> init; |
| init.reserve(staticFields_.size()+1); |
| |
| for (unsigned i = 0, e = staticFields_.size(); i != e; ++i) { |
| const VMField* field = staticFields_[i]; |
| init.push_back(field->buildFieldDescriptor()); |
| } |
| // Null terminate. |
| init.push_back(llvm::Constant::getNullValue(PointerType::get(Type::SByteTy))); |
| |
| const ArrayType* arrayType = |
| ArrayType::get(init.back()->getType(), init.size()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| arrayType, |
| true, |
| GlobalVariable::ExternalLinkage, |
| ConstantArray::get(arrayType, init), |
| getName() + "<static_field_descriptors>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* VMClass::buildStaticFieldPointers() const |
| { |
| std::vector<llvm::Constant*> init; |
| init.reserve(staticFields_.size()); |
| |
| const Type* pointerType = PointerType::get(Type::SByteTy); |
| for (unsigned i = 0, e = staticFields_.size(); i != e; ++i) { |
| const VMField* field = staticFields_[i]; |
| init.push_back(ConstantExpr::getCast(field->getGlobal(), pointerType)); |
| } |
| |
| const ArrayType* arrayType = ArrayType::get(pointerType, init.size()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| arrayType, |
| true, |
| GlobalVariable::ExternalLinkage, |
| ConstantArray::get(arrayType, init), |
| getName() + "<static_field_pointers>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* VMClass::buildMethodDescriptors() const |
| { |
| std::vector<llvm::Constant*> init; |
| init.reserve(getNumStaticMethods() + 1); |
| |
| for (unsigned i = 0, e = getNumDynamicMethods(); i != e; ++i) { |
| const VMMethod* method = getDynamicMethod(i); |
| init.push_back(method->buildMethodDescriptor()); |
| } |
| // Null terminate. |
| init.push_back(llvm::Constant::getNullValue(PointerType::get(Type::SByteTy))); |
| |
| const ArrayType* arrayType = |
| ArrayType::get(init.back()->getType(), init.size()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| arrayType, |
| true, |
| GlobalVariable::ExternalLinkage, |
| ConstantArray::get(arrayType, init), |
| getName() + "<method_descriptors>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* VMClass::buildMethodPointers() const |
| { |
| std::vector<llvm::Constant*> init; |
| init.reserve(getNumStaticMethods()); |
| |
| const Type* pointerType = PointerType::get(Type::SByteTy); |
| for (unsigned i = 0, e = getNumDynamicMethods(); i != e; ++i) { |
| const VMMethod* method = getDynamicMethod(i); |
| init.push_back(ConstantExpr::getCast(method->getBridgeFunction(), |
| pointerType)); |
| } |
| |
| const ArrayType* arrayType = ArrayType::get(pointerType, init.size()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| arrayType, |
| true, |
| GlobalVariable::ExternalLinkage, |
| ConstantArray::get(arrayType, init), |
| getName() + "<method_pointers>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* VMClass::buildStaticMethodDescriptors() const |
| { |
| std::vector<llvm::Constant*> init; |
| init.reserve(getNumStaticMethods() + 1); |
| |
| for (unsigned i = 0, e = getNumStaticMethods(); i != e; ++i) { |
| const VMMethod* method = getStaticMethod(i); |
| init.push_back(method->buildMethodDescriptor()); |
| } |
| // Null terminate. |
| init.push_back(llvm::Constant::getNullValue(PointerType::get(Type::SByteTy))); |
| |
| const ArrayType* arrayType = |
| ArrayType::get(init.back()->getType(), init.size()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| arrayType, |
| true, |
| GlobalVariable::ExternalLinkage, |
| ConstantArray::get(arrayType, init), |
| getName() + "<static_method_descriptors>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* VMClass::buildStaticMethodPointers() const |
| { |
| std::vector<llvm::Constant*> init; |
| init.reserve(getNumStaticMethods()); |
| |
| const Type* pointerType = PointerType::get(Type::SByteTy); |
| for (unsigned i = 0, e = getNumStaticMethods(); i != e; ++i) { |
| const VMMethod* method = getStaticMethod(i); |
| init.push_back(ConstantExpr::getCast(method->getBridgeFunction(), |
| pointerType)); |
| } |
| |
| const ArrayType* arrayType = ArrayType::get(pointerType, init.size()); |
| |
| return ConstantExpr::getPtrPtrFromArrayPtr( |
| new GlobalVariable( |
| arrayType, |
| true, |
| GlobalVariable::ExternalLinkage, |
| ConstantArray::get(arrayType, init), |
| getName() + "<static_method_pointers>", |
| resolver_->getModule())); |
| } |
| |
| llvm::Constant* VMClass::buildClassTypeInfo() const |
| { |
| std::vector<llvm::Constant*> init; |
| init.reserve(5); |
| |
| init.push_back(buildClassName()); |
| init.push_back(ConstantSInt::get(Type::IntTy, getNumSuperClasses())); |
| init.push_back(buildSuperClassRecords()); |
| init.push_back(ConstantSInt::get(Type::IntTy, getInterfaceIndex())); |
| init.push_back(buildInterfaceClassRecords()); |
| if (isArray()) |
| init.push_back(ConstantExpr::getCast(getComponentClass()->getClassRecord(), |
| resolver_->getClassRecordPtrType())); |
| else |
| init.push_back( |
| llvm::Constant::getNullValue(resolver_->getClassRecordPtrType())); |
| if (isArray()) |
| init.push_back( |
| ConstantExpr::getCast( |
| ConstantExpr::getSizeOf(getComponentClass()->getType()), Type::IntTy)); |
| else if (isPrimitive()) |
| init.push_back(ConstantSInt::get(Type::IntTy, -2)); |
| else if (isInterface()) |
| init.push_back(ConstantSInt::get(Type::IntTy, -1)); |
| else // A class. |
| init.push_back(ConstantSInt::get(Type::IntTy, 0)); |
| |
| init.push_back(buildFieldDescriptors()); |
| init.push_back(buildFieldOffsets()); |
| init.push_back(buildStaticFieldDescriptors()); |
| init.push_back(buildStaticFieldPointers()); |
| init.push_back(buildMethodDescriptors()); |
| init.push_back(buildMethodPointers()); |
| init.push_back(buildStaticMethodDescriptors()); |
| init.push_back(buildStaticMethodPointers()); |
| |
| return ConstantStruct::get(init); |
| } |
| |
| void VMClass::computeClassRecord() |
| { |
| DEBUG(std::cerr << "Computing class record for: " << getName() << '\n'); |
| // Find dynamically bound methods. |
| if (!isPrimitive()) { |
| if (const VMClass* superClass = getSuperClass()) |
| dynamicMethods_ = superClass->dynamicMethods_; |
| |
| if (getClassFile()) { |
| const Methods& methods = classFile_->getMethods(); |
| for (unsigned i = 0, e = methods.size(); i != e; ++i) { |
| Method* method = methods[i]; |
| const std::string& name = method->getName()->str(); |
| const std::string& descriptor = method->getDescriptor()->str(); |
| |
| // If method is statically bound just create it. |
| if (method->isPrivate() || method->isStatic() || name[0] == '<') { |
| MethodMap::iterator i = |
| methodMap_.insert( |
| std::make_pair(name + descriptor, VMMethod(this, method))).first; |
| staticMethods_.push_back(&i->second); |
| } |
| // Otherwise we need to assign an index for it and update the |
| // dynamicMethods_ vector. |
| else { |
| const VMMethod* overridenMethod = NULL; |
| for (unsigned i = 0, e = getNumDynamicMethods(); i != e; ++i) { |
| const VMMethod* m = getDynamicMethod(i); |
| if (m->getName() == name && m->getDescriptor() == descriptor) |
| overridenMethod = m; |
| } |
| |
| // If this is an overriden method reuse the method index |
| // with the overriding one. |
| if (overridenMethod) { |
| int index = overridenMethod->getMethodIndex(); |
| MethodMap::iterator i = methodMap_.insert( |
| std::make_pair(name + descriptor, |
| VMMethod(this, method, index))).first; |
| dynamicMethods_[index] = &i->second; |
| } |
| // Otherwise assign it a new index. |
| else { |
| int index = dynamicMethods_.size(); |
| MethodMap::iterator i = methodMap_.insert( |
| std::make_pair( |
| name + descriptor, VMMethod(this, method, index))).first; |
| dynamicMethods_.push_back(&i->second); |
| } |
| } |
| } |
| } |
| } |
| |
| std::vector<llvm::Constant*> init; |
| init.reserve(1 + getNumDynamicMethods()); |
| init.push_back(buildClassTypeInfo()); |
| for (unsigned i = 0, e = getNumDynamicMethods(); i != e; ++i) { |
| const VMMethod* method = getDynamicMethod(i); |
| init.push_back( |
| method->isAbstract() ? |
| llvm::Constant::getNullValue(method->getFunction()->getType()) : |
| method->getFunction()); |
| } |
| |
| llvm::Constant* classRecordInit = ConstantStruct::get(init); |
| resolver_->getModule()->addTypeName("classRecord." + getName(), |
| classRecordInit->getType()); |
| |
| // Now resolve the opaque type of the placeholder class record. |
| const Type* classRecordType = |
| cast<PointerType>(classRecord_->getType())->getElementType(); |
| OpaqueType* opaqueType = cast<OpaqueType>(const_cast<Type*>(classRecordType)); |
| opaqueType->refineAbstractTypeTo(classRecordInit->getType()); |
| // Set the initializer of the class record. |
| classRecord_->setInitializer(classRecordInit); |
| // Mark the class record as constant. |
| classRecord_->setConstant(true); |
| |
| DEBUG(std::cerr << "Computed class record for: " << getName() << '\n'); |
| } |
| |
| void VMClass::link() |
| { |
| // Primitive classes require no linking. |
| if (isPrimitive()) |
| ; |
| else if (isArray()) { |
| superClasses_.reserve(1); |
| superClasses_.push_back(resolver_->getClass("java/lang/Object")); |
| |
| interfaces_.reserve(2); |
| interfaces_.push_back(resolver_->getClass("java/lang/Cloneable")); |
| interfaces_.push_back(resolver_->getClass("java/io/Serializable")); |
| } |
| else { |
| // This is any class but java/lang/Object. |
| if (classFile_->getSuperClass()) { |
| // Our direct super class. |
| const VMClass* superClass = getClass(classFile_->getSuperClassIndex()); |
| |
| // Add the interfaces of our direct superclass. |
| for (unsigned i = 0, e = superClass->getNumInterfaces(); i != e; ++i) |
| interfaces_.push_back(superClass->getInterface(i)); |
| |
| // The first class is the direct super class of this class. |
| superClasses_.reserve(superClass->getNumSuperClasses() + 1); |
| superClasses_.push_back(superClass); |
| for (unsigned i = 0, e = superClass->getNumSuperClasses(); i != e; ++i) |
| superClasses_.push_back(superClass->getSuperClass(i)); |
| } |
| |
| // For each of the interfaces we implement, load it and add that |
| // interface and all the interfaces it inherits from. |
| for (unsigned i = 0, e = classFile_->getNumInterfaces(); i != e; ++i) { |
| const VMClass* interface = getClass(classFile_->getInterfaceIndex(i)); |
| interfaces_.push_back(interface); |
| for (unsigned j = 0, f = interface->getNumInterfaces(); j != f; ++j) |
| interfaces_.push_back(interface->getInterface(j)); |
| } |
| |
| // Sort the interfaces array and remove duplicates. |
| std::sort(interfaces_.begin(), interfaces_.end()); |
| interfaces_.erase(std::unique(interfaces_.begin(), interfaces_.end()), |
| interfaces_.end()); |
| } |
| |
| // The interface index for an interface is a unique number generated |
| // from the resolver. |
| if (isInterface()) |
| interfaceIndex_ = resolver_->getNextInterfaceIndex(); |
| // For a class it is the max index of all the interfaces it implements. |
| else { |
| for (unsigned i = 0, e = getNumInterfaces(); i != e; ++i) |
| interfaceIndex_ = |
| std::max(interfaceIndex_, getInterface(i)->getInterfaceIndex()); |
| } |
| |
| computeLayout(); |
| computeClassRecord(); |
| |
| assert(!isa<OpaqueType>(getLayoutType()) &&"Class not initialized properly!"); |
| } |
| |
| llvm::Constant* VMClass::getConstant(unsigned index) const |
| { |
| assert(classFile_ && "No constant pool!"); |
| assert((dynamic_cast<ConstantString*>(classFile_->getConstant(index)) || |
| dynamic_cast<ConstantInteger*>(classFile_->getConstant(index)) || |
| dynamic_cast<ConstantFloat*>(classFile_->getConstant(index)) || |
| dynamic_cast<ConstantLong*>(classFile_->getConstant(index)) || |
| dynamic_cast<ConstantDouble*>(classFile_->getConstant(index))) && |
| "Not an index to a constant!"); |
| |
| // If we haven't resolved this constant already, do so now. |
| if (!resolvedConstantPool_[index]) { |
| Constant* jc = classFile_->getConstant(index); |
| if (ConstantString* s = dynamic_cast<ConstantString*>(jc)) { |
| const VMClass* stringClass = resolver_->getClass("java/lang/String"); |
| const Type* stringType = stringClass->getLayoutType(); |
| resolvedConstantPool_[index] = |
| new GlobalVariable(stringType, |
| false, |
| GlobalVariable::LinkOnceLinkage, |
| llvm::Constant::getNullValue(stringType), |
| s->getValue()->str() + ".java/lang/String", |
| resolver_->getModule()); |
| } |
| else if (ConstantInteger* i = dynamic_cast<ConstantInteger*>(jc)) |
| resolvedConstantPool_[index] = |
| ConstantSInt::get(Type::IntTy, i->getValue()); |
| else if (ConstantFloat* f = dynamic_cast<ConstantFloat*>(jc)) |
| resolvedConstantPool_[index] = |
| ConstantFP::get(Type::FloatTy, f->getValue()); |
| else if (ConstantLong* l = dynamic_cast<ConstantLong*>(jc)) |
| resolvedConstantPool_[index] = |
| ConstantSInt::get(Type::LongTy, l->getValue()); |
| else if (ConstantDouble* d = dynamic_cast<ConstantDouble*>(jc)) |
| resolvedConstantPool_[index] = |
| ConstantFP::get(Type::DoubleTy, d->getValue()); |
| else |
| assert(0 && "Not a constant!"); |
| } |
| |
| return static_cast<llvm::Constant*>(resolvedConstantPool_[index]); |
| } |
| |
| const VMClass* VMClass::getClass(unsigned index) const |
| { |
| assert(classFile_ && "No constant pool!"); |
| assert((dynamic_cast<ConstantClass*>(classFile_->getConstant(index)) || |
| dynamic_cast<ConstantUtf8*>(classFile_->getConstant(index))) && |
| "Not an index to a class or descriptor reference!"); |
| |
| // If we haven't resolved this constant already, do so now. |
| if (!resolvedConstantPool_[index]) { |
| Constant* jc = classFile_->getConstant(index); |
| if (ConstantClass* c = dynamic_cast<ConstantClass*>(jc)) |
| resolvedConstantPool_[index] = |
| const_cast<VMClass*>(resolver_->getClass(c->getName()->str())); |
| else if (ConstantUtf8* d = dynamic_cast<ConstantUtf8*>(jc)) |
| resolvedConstantPool_[index] = |
| const_cast<VMClass*>(resolver_->getClassForDesc(d->str())); |
| else |
| assert(0 && "Not a class!"); |
| } |
| |
| return static_cast<const VMClass*>(resolvedConstantPool_[index]); |
| } |
| |
| const VMField* VMClass::getField(unsigned index) const |
| { |
| assert(classFile_ && "No constant pool!"); |
| assert(dynamic_cast<ConstantFieldRef*>(classFile_->getConstant(index)) && |
| "Not an index to a field reference!"); |
| |
| // If we haven't resolved this constant already, do so now. |
| if (!resolvedConstantPool_[index]) { |
| ConstantFieldRef* jc = classFile_->getConstantFieldRef(index); |
| const VMClass* clazz = getClass(jc->getClassIndex()); |
| const std::string& name = jc->getNameAndType()->getName()->str(); |
| resolvedConstantPool_[index] = |
| const_cast<VMField*>(clazz->lookupField(name)); |
| } |
| |
| return static_cast<const VMField*>(resolvedConstantPool_[index]); |
| } |
| |
| const VMMethod* VMClass::getMethod(unsigned index) const |
| { |
| assert(classFile_ && "No constant pool!"); |
| assert((dynamic_cast<ConstantMethodRef*>(classFile_->getConstant(index)) || |
| dynamic_cast<ConstantInterfaceMethodRef*>(classFile_->getConstant(index))) && |
| "Not an index to a method reference!"); |
| |
| // If we haven't resolved this constant already, do so now. |
| if (!resolvedConstantPool_[index]) { |
| ConstantMemberRef* jc = classFile_->getConstantMemberRef(index); |
| const VMClass* clazz = getClass(jc->getClassIndex()); |
| ConstantNameAndType* ntc = jc->getNameAndType(); |
| const std::string& name = ntc->getName()->str(); |
| const std::string& descriptor = ntc->getDescriptor()->str(); |
| resolvedConstantPool_[index] = |
| const_cast<VMMethod*>(clazz->lookupMethod(name + descriptor)); |
| } |
| |
| return static_cast<const VMMethod*>(resolvedConstantPool_[index]); |
| } |