blob: bc76ce2f0f2ffc98d9f381a3e703ea742fc9f13b [file] [log] [blame]
#ifndef _J3_CODE_GEN_H_
#define _J3_CODE_GEN_H_
#include "llvm/IR/IRBuilder.h"
#include "j3/j3codegenvar.h"
#include "j3/j3codegenexception.h"
namespace llvm {
class Function;
class Value;
}
namespace vmkit {
class BumpAllocator;
}
namespace j3 {
class J3;
class J3Type;
class J3Class;
class J3ArrayClass;
class J3ClassLoader;
class J3Field;
class J3Method;
class J3Signature;
class J3Reader;
class J3ObjectType;
class J3Signature;
class J3OpInfo {
public:
llvm::Instruction* insn;
llvm::BasicBlock* bb;
llvm::Type** metaStack;
size_t topStack;
};
class J3CodeGen {
public:
enum {
WithMethod = 1,
WithCaller = 2,
OnlyTranslate = 4,
NotUseStub = 8,
NotNeedGC = 16,
SupposeClinited = 32,
NoRuntimeCheck = 64
};
bool withMethod() { return mode & WithMethod; }
bool withCaller() { return mode & WithCaller; }
bool onlyTranslate() { return mode & OnlyTranslate; }
bool useStub() { return !(mode & NotUseStub); }
bool needGC() { return !(mode & NotNeedGC); }
bool supposeClinited() { return mode & SupposeClinited; }
bool noRuntimeCheck() { return mode & NoRuntimeCheck; }
private:
friend class J3CodeGenVar;
friend class J3ExceptionTable;
friend class J3ExceptionNode;
friend class J3Signature;
uint32_t mode;
vmkit::BumpAllocator* allocator;
llvm::Module* module;
llvm::IRBuilder<> builder;
llvm::Function* llvmFunction;
J3* vm;
J3Class* cl;
J3ClassLoader* loader;
J3Method* method;
J3Signature* signature;
J3Reader* codeReader;
uint32_t access;
llvm::BasicBlock* bbCheckCastFailed;
llvm::BasicBlock* bbNullCheckFailed;
llvm::BasicBlock* bbRet;
J3ExceptionTable exceptions;
uint32_t curExceptionNode;
J3OpInfo* opInfos;
uint32_t* pendingBranchs;
uint32_t topPendingBranchs;
llvm::Type* uintPtrTy;
llvm::Value* nullValue;
llvm::MDNode* dbgInfo;
uint32_t javaPC;
uint32_t bc;
J3CodeGenVar locals;
J3CodeGenVar stack;
J3CodeGenVar ret;
bool closeBB;
bool isWide;
uint32_t wideReadU1();
uint32_t wideReadS1();
llvm::Function* buildFunction(J3Method* method, bool isStub=1);
llvm::Value* typeDescriptor(J3ObjectType* objectType, llvm::Type* type);
llvm::Value* currentThread();
llvm::Value* nullCheck(llvm::Value* obj);
llvm::BasicBlock* newBB(const char* name);
bool onEndPoint();
llvm::BasicBlock* forwardBranch(const char* id, uint32_t pc, bool doAlloc, bool doPush);
void condBr(llvm::Value* op);
llvm::Value* flatten(llvm::Value* v);
llvm::Value* unflatten(llvm::Value* v, llvm::Type* type);
llvm::Value* handleToObject(llvm::Value* obj);
llvm::Value* javaClass(J3ObjectType* type, bool doPush);
llvm::Value* staticObject(J3Class* cl);
llvm::Value* vt(J3ObjectType* cl);
llvm::Value* vt(llvm::Value* obj);
void resolveJ3ObjectType(J3ObjectType* cl);
void initialiseJ3ObjectType(J3ObjectType* cl);
void monitorEnter(llvm::Value* obj);
void monitorExit(llvm::Value* obj);
llvm::CallInst* isAssignableTo(llvm::Value* obj, J3ObjectType* type);
void instanceof(llvm::Value* obj, J3ObjectType* type);
void checkCast(llvm::Value* obj, J3ObjectType* type);
void floatToInteger(J3Type* from, J3Type* to);
void compareFP(bool isL);
void compareLong();
llvm::Value* fieldOffset(llvm::Value* obj, J3Field* f);
void get(llvm::Value* obj, J3Field* field);
void getField(uint32_t idx);
void getStatic(uint32_t idx);
void put(llvm::Value* obj, llvm::Value* val, J3Field* field);
void putField(uint32_t idx);
void putStatic(uint32_t idx);
void invoke(uint32_t access, J3Method* method, llvm::Value* func);
void invokeVirtual(uint32_t idx);
void invokeStatic(uint32_t idx);
void invokeSpecial(uint32_t idx);
void invokeInterface(uint32_t idx);
llvm::Value* arrayContent(J3Type* cType, llvm::Value* array, llvm::Value* idx);
void arrayBoundCheck(llvm::Value* obj, llvm::Value* idx);
llvm::Value* arrayLength(llvm::Value* obj);
llvm::Value* arrayLengthPtr(llvm::Value* obj);
void arrayStore(J3Type* cType);
void arrayLoad(J3Type* cType);
void multianewArray();
void newArray(uint8_t atype);
void newArray(J3ArrayClass* type);
void newObject(J3Class* cl);
void lookupSwitch();
void tableSwitch();
void ldc(uint32_t idx);
void selectExceptionNode(uint32_t idx);
void translate();
void initExceptionNode(J3ExceptionNode** pnode, uint32_t pc, J3ExceptionNode* node);
void addToExceptionNode(J3ExceptionNode* node, J3ExceptionEntry* entry);
void closeExceptionNode(J3ExceptionNode* node);
void generateJava();
void generateNative();
llvm::Function* lookupNative();
llvm::Type* doNativeType(llvm::Type* type);
llvm::Value* buildString(const char* msg);
static void echoDebugEnter(uint32_t isLeave, const char* msg, ...);
static void echoDebugExecute(uint32_t level, const char* msg, ...);
static void echoElement(uint32_t level, uint32_t type, uintptr_t elmt);
void genEchoElement(const char* msg, uint32_t idx, llvm::Value* val);
void genDebugOpcode();
void genDebugEnterLeave(bool isLeave);
#define _x(name, id, forceInline) \
llvm::Function* name;
#include "j3/j3meta.def"
#undef _x
llvm::GlobalValue* gvTypeInfo; /* typename void* */
llvm::Function* gcRoot;
llvm::Function* stackMap;
llvm::Function* patchPoint64;
llvm::Function* patchPointVoid;
J3CodeGen(vmkit::BumpAllocator* _allocator, J3Method* method, uint32_t mode);
~J3CodeGen();
void* operator new(size_t n, vmkit::BumpAllocator* _allocator);
void operator delete(void* ptr);
public:
static void translate(J3Method* method, uint32_t mode);
};
}
#endif