blob: 83ab6aeac410840f3ba5f34c67030b46fc187288 [file] [log] [blame]
//===-- ClassFile.h - ClassFile support library -----------------*- 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 ClassFile and subordinate
// classes, which represent a parsed class file.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_JAVA_CLASSFILE_H
#define LLVM_JAVA_CLASSFILE_H
#include <llvm/System/Path.h>
#include <iosfwd>
#include <stdexcept>
#include <vector>
#include <llvm/Support/DataTypes.h>
namespace llvm { namespace Java {
// Forward declarations
class Attribute;
class ConstantValueAttribute;
class CodeAttribute;
class ExceptionsAttribute;
class Constant;
class ConstantClass;
class ConstantFieldRef;
class ConstantInterfaceMethodRef;
class ConstantMemberRef;
class ConstantMethodRef;
class ConstantNameAndType;
class ConstantUtf8;
class ClassFile;
class Field;
class Method;
enum AccessFlag {
ACC_PUBLIC = 0x0001,
ACC_PRIVATE = 0x0002,
ACC_PROTECTED = 0x0004,
ACC_STATIC = 0x0008,
ACC_FINAL = 0x0010,
ACC_SUPER = 0x0020,
ACC_SYNCHRONIZED = 0x0020,
ACC_VOLATILE = 0x0040,
ACC_TRANSIENT = 0x0080,
ACC_NATIVE = 0x0100,
ACC_INTERFACE = 0x0200,
ACC_ABSTRACT = 0x0400,
ACC_STRICT = 0x0800,
};
typedef std::vector<Constant*> ConstantPool;
typedef std::vector<Field*> Fields;
typedef std::vector<Method*> Methods;
typedef std::vector<Attribute*> Attributes;
Attribute* getAttribute(const Attributes& attrs,
const std::string& name);
class ClassFile {
static const ClassFile* readClassFile(std::istream& is);
static std::vector<llvm::sys::Path> getClassPath();
static sys::Path getFileForClass(const std::string& classname);
public:
static const ClassFile* get(const std::string& classname);
~ClassFile();
uint16_t getMinorVersion() const { return minorV_; }
uint16_t getMajorVersion() const { return majorV_; }
unsigned getNumConstants() const { return cPool_.size(); }
Constant* getConstant(unsigned index) const { return cPool_[index]; }
ConstantClass* getConstantClass(unsigned index) const;
ConstantMemberRef* getConstantMemberRef(unsigned index) const;
ConstantFieldRef* getConstantFieldRef(unsigned index) const;
ConstantMethodRef* getConstantMethodRef(unsigned index) const;
ConstantInterfaceMethodRef*
getConstantInterfaceMethodRef(unsigned index) const;
ConstantNameAndType* getConstantNameAndType(unsigned index) const;
ConstantUtf8* getConstantUtf8(unsigned index) const;
bool isPublic() const { return accessFlags_ & ACC_PUBLIC; }
bool isFinal() const { return accessFlags_ & ACC_FINAL; }
bool isSuper() const { return accessFlags_ & ACC_SUPER; }
bool isInterface() const { return accessFlags_ & ACC_INTERFACE; }
bool isAbstract() const { return accessFlags_ & ACC_ABSTRACT; }
unsigned getThisClassIndex() const { return thisClassIdx_; }
ConstantClass* getThisClass() const {
return getConstantClass(thisClassIdx_);
}
unsigned getSuperClassIndex() const { return superClassIdx_; }
ConstantClass* getSuperClass() const {
return superClassIdx_ ? getConstantClass(superClassIdx_) : NULL;
}
unsigned getNumInterfaces() const { return interfaces_.size(); }
unsigned getInterfaceIndex(unsigned i) const { return interfaces_[i]; }
ConstantClass* getInterface(unsigned i) const {
return getConstantClass(getInterfaceIndex(i));
}
const Fields& getFields() const { return fields_; }
const Methods& getMethods() const { return methods_; }
const Attributes& getAttributes() const { return attributes_; }
bool isNativeMethodOverloaded(const Method& method) const;
std::ostream& dump(std::ostream& os) const;
private:
uint16_t majorV_;
uint16_t minorV_;
ConstantPool cPool_;
uint16_t accessFlags_;
uint16_t thisClassIdx_;
uint16_t superClassIdx_;
std::vector<uint16_t> interfaces_;
Fields fields_;
Methods methods_;
Attributes attributes_;
ClassFile(std::istream& is);
};
inline std::ostream& operator<<(std::ostream& os, const ClassFile& c) {
return c.dump(os);
}
class Constant {
protected:
const ClassFile* parent_;
Constant(const ClassFile* cf)
: parent_(cf) { }
public:
enum Tag {
CLASS = 7,
FIELD_REF = 9,
METHOD_REF = 10,
INTERFACE_METHOD_REF = 11,
STRING = 8,
INTEGER = 3,
FLOAT = 4,
LONG = 5,
DOUBLE = 6,
NAME_AND_TYPE = 12,
UTF8 = 1
};
static Constant* readConstant(const ClassFile* cf, std::istream& is);
virtual bool isSingleSlot() { return true; }
bool isDoubleSlot() { return !isSingleSlot(); }
const ClassFile* getParent() { return parent_; }
virtual ~Constant();
virtual std::ostream& dump(std::ostream& os) const = 0;
};
inline std::ostream& operator<<(std::ostream& os, const Constant& c) {
return c.dump(os);
}
class ConstantClass : public Constant {
uint16_t nameIdx_;
public:
ConstantClass(const ClassFile* cf, std::istream& is);
unsigned getNameIndex() const { return nameIdx_; }
ConstantUtf8* getName() const {
return parent_->getConstantUtf8(nameIdx_);
}
std::ostream& dump(std::ostream& os) const;
};
class ConstantMemberRef : public Constant {
protected:
uint16_t classIdx_;
uint16_t nameAndTypeIdx_;
ConstantMemberRef(const ClassFile* cf, std::istream& is);
public:
unsigned getClassIndex() const { return classIdx_; }
ConstantClass* getClass() const {
return parent_->getConstantClass(classIdx_);
}
unsigned getNameAndTypeIndex() const { return nameAndTypeIdx_; }
ConstantNameAndType* getNameAndType() const {
return parent_->getConstantNameAndType(nameAndTypeIdx_);
}
};
class ConstantFieldRef : public ConstantMemberRef {
public:
ConstantFieldRef(const ClassFile* cf, std::istream& is)
: ConstantMemberRef(cf, is) { }
std::ostream& dump(std::ostream& os) const;
};
class ConstantMethodRef : public ConstantMemberRef {
public:
ConstantMethodRef(const ClassFile* cf, std::istream& is)
: ConstantMemberRef(cf, is) { }
std::ostream& dump(std::ostream& os) const;
};
class ConstantInterfaceMethodRef : public ConstantMemberRef {
public:
ConstantInterfaceMethodRef(const ClassFile* cf, std::istream& is)
: ConstantMemberRef(cf, is) { }
std::ostream& dump(std::ostream& os) const;
};
class ConstantString : public Constant {
uint16_t stringIdx_;
public:
ConstantString(const ClassFile* cf, std::istream& is);
unsigned getStringIndex() const { return stringIdx_; }
ConstantUtf8* getValue() const {
return parent_->getConstantUtf8(stringIdx_);
}
std::ostream& dump(std::ostream& os) const;
};
class ConstantInteger : public Constant {
int32_t value_;
public:
ConstantInteger(const ClassFile* cf, std::istream& is);
int32_t getValue() const { return value_; }
std::ostream& dump(std::ostream& os) const;
};
class ConstantFloat : public Constant {
float value_;
public:
ConstantFloat(const ClassFile* cf, std::istream& is);
float getValue() const { return value_; }
std::ostream& dump(std::ostream& os) const;
};
class ConstantLong : public Constant {
int64_t value_;
public:
ConstantLong(const ClassFile* cf, std::istream& is);
virtual bool isSingleSlot() { return false; }
int64_t getValue() const { return value_; }
std::ostream& dump(std::ostream& os) const;
};
class ConstantDouble : public Constant {
double value_;
public:
ConstantDouble(const ClassFile* cf, std::istream& is);
virtual bool isSingleSlot() { return false; }
double getValue() const { return value_; }
std::ostream& dump(std::ostream& os) const;
};
class ConstantNameAndType : public Constant {
uint16_t nameIdx_;
uint16_t descriptorIdx_;
public:
ConstantNameAndType(const ClassFile* cf, std::istream& is);
unsigned getNameIndex() const { return nameIdx_; }
ConstantUtf8* getName() const {
return parent_->getConstantUtf8(nameIdx_);
}
unsigned getDescriptorIndex() const { return descriptorIdx_; }
ConstantUtf8* getDescriptor() const {
return parent_->getConstantUtf8(descriptorIdx_);
}
std::ostream& dump(std::ostream& os) const;
};
class ConstantUtf8 : public Constant {
std::string utf8_;
public:
ConstantUtf8(const ClassFile* cf, std::istream& is);
const std::string& str() const { return utf8_; }
std::ostream& dump(std::ostream& os) const;
};
class Member {
protected:
const ClassFile* parent_;
uint16_t accessFlags_;
uint16_t nameIdx_;
uint16_t descriptorIdx_;
Attributes attributes_;
Member(const ClassFile* parent, std::istream& is);
~Member();
public:
bool isPublic() const { return accessFlags_ & ACC_PUBLIC; }
bool isPrivate() const { return accessFlags_ & ACC_PRIVATE; }
bool isProtected() const { return accessFlags_ & ACC_PROTECTED; }
bool isStatic() const { return accessFlags_ & ACC_STATIC; }
bool isFinal() const { return accessFlags_ & ACC_FINAL; }
const ClassFile* getParent() const { return parent_; }
unsigned getNameIndex() const { return nameIdx_; }
ConstantUtf8* getName() const { return parent_->getConstantUtf8(nameIdx_); }
unsigned getDescriptorIndex() const { return descriptorIdx_; }
ConstantUtf8* getDescriptor() const {
return parent_->getConstantUtf8(descriptorIdx_);
}
const Attributes& getAttributes() const { return attributes_; }
};
class Field : public Member {
private:
Field(const ClassFile* parent, std::istream& is);
public:
static Field* readField(const ClassFile* parent, std::istream& is) {
return new Field(parent, is);
}
~Field();
bool isVolatile() const { return accessFlags_ & ACC_VOLATILE; }
bool isTransient() const { return accessFlags_ & ACC_TRANSIENT; }
ConstantValueAttribute* getConstantValueAttribute() const;
std::ostream& dump(std::ostream& os) const;
};
inline std::ostream& operator<<(std::ostream& os, const Field& f) {
return f.dump(os);
}
class Method : public Member {
Method(const ClassFile* parent, std::istream& is);
public:
static Method* readMethod(const ClassFile* parent, std::istream& is) {
return new Method(parent, is);
}
~Method();
bool isSynchronized() const { return accessFlags_ & ACC_SYNCHRONIZED; }
bool isNative() const { return accessFlags_ & ACC_NATIVE; }
bool isAbstract() const { return accessFlags_ & ACC_ABSTRACT; }
bool isStrict() const { return accessFlags_ & ACC_STRICT; }
CodeAttribute* getCodeAttribute() const;
ExceptionsAttribute* getExceptionsAttribute() const;
std::ostream& dump(std::ostream& os) const;
};
inline std::ostream& operator<<(std::ostream& os, const Method& m) {
return m.dump(os);
}
class Attribute {
protected:
const ClassFile* parent_;
uint16_t nameIdx_;
Attribute(const ClassFile* cf, uint16_t nameIdx, std::istream& is);
public:
static Attribute* readAttribute(const ClassFile* cf, std::istream& is);
virtual ~Attribute();
unsigned getNameIndex() const { return nameIdx_; }
ConstantUtf8* getName() const { return parent_->getConstantUtf8(nameIdx_); }
virtual std::ostream& dump(std::ostream& os) const;
static const std::string CONSTANT_VALUE;
static const std::string CODE;
static const std::string EXCEPTIONS;
static const std::string INNER_CLASSES;
static const std::string SYNTHETIC;
static const std::string SOURCE_FILE;
static const std::string LINE_NUMBER_TABLE;
static const std::string LOCAL_VARIABLE_TABLE;
static const std::string DEPRECATED;
};
inline std::ostream& operator<<(std::ostream& os, const Attribute& a) {
return a.dump(os);
}
class ConstantValueAttribute : public Attribute {
uint16_t valueIdx_;
public:
ConstantValueAttribute(const ClassFile* cf,
uint16_t nameIdx,
std::istream& is);
unsigned getValueIndex() const { return valueIdx_; }
Constant* getValue() const { return parent_->getConstant(valueIdx_); }
std::ostream& dump(std::ostream& os) const;
};
class CodeAttribute : public Attribute {
public:
class Exception {
const ClassFile* parent_;
uint16_t startPc_;
uint16_t endPc_;
uint16_t handlerPc_;
uint16_t catchTypeIdx_;
public:
Exception(const ClassFile* cf, std::istream& is);
uint16_t getStartPc() const { return startPc_; }
uint16_t getEndPc() const { return endPc_; }
uint16_t getHandlerPc() const { return handlerPc_; }
uint16_t getCatchTypeIndex() const { return catchTypeIdx_; }
ConstantClass* getCatchType() const {
return catchTypeIdx_ ? NULL : parent_->getConstantClass(catchTypeIdx_);
}
std::ostream& dump(std::ostream& os) const;
};
typedef std::vector<Exception*> Exceptions;
private:
uint16_t maxStack_;
uint16_t maxLocals_;
uint32_t codeSize_;
uint8_t* code_;
Exceptions exceptions_;
Attributes attributes_;
public:
CodeAttribute(const ClassFile* cf, uint16_t nameIdx, std::istream& is);
~CodeAttribute();
uint16_t getMaxStack() const { return maxStack_; }
uint16_t getMaxLocals() const { return maxLocals_; }
const uint8_t* getCode() const { return code_; }
uint32_t getCodeSize() const { return codeSize_; }
const Exceptions& getExceptions() const { return exceptions_; }
const Attributes& getAttributes() const { return attributes_; }
std::ostream& dump(std::ostream& os) const;
};
inline std::ostream& operator<<(std::ostream& os,
const CodeAttribute::Exception& e) {
return e.dump(os);
}
class ExceptionsAttribute : public Attribute {
private:
uint16_t nameIdx_;
std::vector<uint16_t> exceptions_;
public:
ExceptionsAttribute(const ClassFile* cf,
uint16_t nameIdx,
std::istream& is);
unsigned getNumExceptions() const { return exceptions_.size(); }
unsigned getExceptionIndex(unsigned i) const { return exceptions_[i]; }
ConstantClass* getException(unsigned i) const {
return parent_->getConstantClass(getExceptionIndex(i));
}
std::ostream& dump(std::ostream& os) const;
};
class ClassFileParseError : public std::exception {
std::string msg_;
public:
explicit ClassFileParseError(const std::string& msg) : msg_(msg) { }
virtual ~ClassFileParseError() throw();
virtual const char* what() const throw() { return msg_.c_str(); }
};
class ClassFileSemanticError : public std::exception {
std::string msg_;
public:
explicit ClassFileSemanticError(const std::string& msg) : msg_(msg) { }
virtual ~ClassFileSemanticError() throw();
virtual const char* what() const throw() { return msg_.c_str(); }
};
class ClassNotFoundException : public std::exception {
std::string msg_;
public:
explicit ClassNotFoundException(const std::string& msg) : msg_(msg) { }
virtual ~ClassNotFoundException() throw();
virtual const char* what() const throw() { return msg_.c_str(); }
};
class InvocationTargetException : public std::exception {
std::string msg_;
public:
explicit InvocationTargetException(const std::string& msg) : msg_(msg) { }
virtual ~InvocationTargetException() throw();
virtual const char* what() const throw() { return msg_.c_str(); }
};
} } // namespace llvm::Java
#endif//LLVM_JAVA_CLASSFILE_H