|  | //===--- LLVMInfo.cpp - Implementation of LLVM info objects for J3---------===// | 
|  | // | 
|  | //                            The VMKit project | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/IR/BasicBlock.h" | 
|  | #include "llvm/IR/CallingConv.h" | 
|  | #include "llvm/IR/Constants.h" | 
|  | #include "llvm/IR/Instructions.h" | 
|  | #include "llvm/IR/Module.h" | 
|  | #include "llvm/Support/CommandLine.h" | 
|  | #include "llvm/Support/MutexGuard.h" | 
|  | #include "llvm/IR/DataLayout.h" | 
|  |  | 
|  |  | 
|  | #include "vmkit/JIT.h" | 
|  |  | 
|  | #include "JavaConstantPool.h" | 
|  | #include "JavaString.h" | 
|  | #include "JavaThread.h" | 
|  | #include "JavaTypes.h" | 
|  | #include "JavaUpcalls.h" | 
|  | #include "Jnjvm.h" | 
|  | #include "Reader.h" | 
|  |  | 
|  | #include "j3/JavaLLVMCompiler.h" | 
|  | #include "j3/LLVMInfo.h" | 
|  |  | 
|  | #include <cstdio> | 
|  |  | 
|  | using namespace j3; | 
|  | using namespace llvm; | 
|  |  | 
|  | Type* LLVMClassInfo::getVirtualType() { | 
|  | if (!virtualType) { | 
|  | std::vector<llvm::Type*> fields; | 
|  | const DataLayout* targetData = Compiler->TheDataLayout; | 
|  | const StructLayout* sl = 0; | 
|  | StructType* structType = 0; | 
|  | LLVMContext& context = Compiler->getLLVMModule()->getContext(); | 
|  |  | 
|  | if (classDef->super) { | 
|  | LLVMClassInfo* CLI = Compiler->getClassInfo(classDef->super); | 
|  | llvm::Type* Ty = CLI->getVirtualType()->getContainedType(0); | 
|  | fields.push_back(Ty); | 
|  |  | 
|  | for (uint32 i = 0; i < classDef->nbVirtualFields; ++i) { | 
|  | JavaField& field = classDef->virtualFields[i]; | 
|  | Typedef* type = field.getSignature(); | 
|  | LLVMAssessorInfo& LAI = Compiler->getTypedefInfo(type); | 
|  | fields.push_back(LAI.llvmType); | 
|  | } | 
|  |  | 
|  |  | 
|  | structType = StructType::get(context, fields, false); | 
|  | virtualType = PointerType::getUnqual(structType); | 
|  | sl = targetData->getStructLayout(structType); | 
|  |  | 
|  | } else { | 
|  | virtualType = Compiler->getIntrinsics()->JavaObjectType; | 
|  | assert(virtualType && "intrinsics not initalized"); | 
|  | structType = dyn_cast<StructType>(virtualType->getContainedType(0)); | 
|  | sl = targetData->getStructLayout(structType); | 
|  |  | 
|  | } | 
|  |  | 
|  | uint64 size = targetData->getTypeAllocSize(structType); | 
|  | virtualSizeConstant = ConstantInt::get(Type::getInt32Ty(context), size); | 
|  |  | 
|  | // TODO: put that elsewhere. | 
|  | // The class is resolved if it was precompiled. | 
|  | if ((!classDef->isResolved() || Compiler->isStaticCompiling()) | 
|  | && Compiler == classDef->classLoader->getCompiler()) { | 
|  | for (uint32 i = 0; i < classDef->nbVirtualFields; ++i) { | 
|  | JavaField& field = classDef->virtualFields[i]; | 
|  | field.ptrOffset = sl->getElementOffset(i + 1); | 
|  | field.num = i + 1; | 
|  | } | 
|  |  | 
|  | classDef->virtualSize = (uint32)size; | 
|  | classDef->alignment = sl->getAlignment(); | 
|  |  | 
|  | Compiler->makeVT(classDef); | 
|  | Compiler->makeIMT(classDef); | 
|  | } | 
|  | } | 
|  |  | 
|  | return virtualType; | 
|  | } | 
|  |  | 
|  | Type* LLVMClassInfo::getStaticType() { | 
|  |  | 
|  | if (!staticType) { | 
|  | Class* cl = (Class*)classDef; | 
|  | std::vector<llvm::Type*> fields; | 
|  |  | 
|  | LLVMContext& context = Compiler->getLLVMModule()->getContext(); | 
|  |  | 
|  | for (uint32 i = 0; i < classDef->nbStaticFields; ++i) { | 
|  | JavaField& field = classDef->staticFields[i]; | 
|  | Typedef* type = field.getSignature(); | 
|  | LLVMAssessorInfo& LAI = Compiler->getTypedefInfo(type); | 
|  | fields.push_back(LAI.llvmType); | 
|  | } | 
|  |  | 
|  | StructType* structType = StructType::get(context, fields, false); | 
|  | staticType = PointerType::getUnqual(structType); | 
|  | const DataLayout* targetData = Compiler->TheDataLayout; | 
|  | const StructLayout* sl = targetData->getStructLayout(structType); | 
|  |  | 
|  | // TODO: put that elsewhere. | 
|  | if (Compiler == classDef->classLoader->getCompiler()) { | 
|  | for (uint32 i = 0; i < classDef->nbStaticFields; ++i) { | 
|  | JavaField& field = classDef->staticFields[i]; | 
|  | field.num = i; | 
|  | field.ptrOffset = sl->getElementOffset(i); | 
|  | } | 
|  |  | 
|  | uint64 size = targetData->getTypeAllocSize(structType); | 
|  | cl->staticSize = size; | 
|  | } | 
|  | } | 
|  | return staticType; | 
|  | } | 
|  |  | 
|  |  | 
|  | Value* LLVMClassInfo::getVirtualSize() { | 
|  | if (!virtualSizeConstant) { | 
|  | getVirtualType(); | 
|  | assert(virtualSizeConstant && "No size for a class?"); | 
|  | } | 
|  | return virtualSizeConstant; | 
|  | } | 
|  |  | 
|  | static char* GetMethodName(vmkit::ThreadAllocator& allocator, | 
|  | JavaMethod* methodDef, | 
|  | Class* customizeFor) { | 
|  | const UTF8* jniConsClName = methodDef->classDef->name; | 
|  | const UTF8* jniConsName = methodDef->name; | 
|  | const UTF8* jniConsType = methodDef->type; | 
|  | sint32 clen = jniConsClName->size; | 
|  | sint32 mnlen = jniConsName->size; | 
|  | sint32 mtlen = jniConsType->size; | 
|  |  | 
|  | char* buf = (char*)allocator.Allocate( | 
|  | 3 + JNI_NAME_PRE_LEN + 1 + ((mnlen + clen + mtlen) << 3)); | 
|  |  | 
|  | methodDef->jniConsFromMethOverloaded(buf + 1); | 
|  | memcpy(buf, "JnJVM", 5); | 
|  |  | 
|  | if (customizeFor != NULL) { | 
|  | int len = strlen(buf); | 
|  | UTF8Buffer buffer(customizeFor->name); | 
|  | buffer.toCompileName("_Customized"); | 
|  | buf[len] = '_'; | 
|  | buf[len + 1] = '_'; | 
|  | memcpy(buf + len + 2, buffer.cString(), strlen(buffer.cString()) + 1); | 
|  | } | 
|  |  | 
|  | return buf; | 
|  | } | 
|  |  | 
|  | Function* LLVMMethodInfo::getMethod(Class* customizeFor) { | 
|  | assert(!isAbstract(methodDef->access)); | 
|  | bool customizing = false; | 
|  | Function* result = NULL; | 
|  | if (customizeFor != NULL && isCustomizable) { | 
|  | customizing = true; | 
|  | result = customizedVersions[customizeFor]; | 
|  | } else { | 
|  | result = methodFunction; | 
|  | } | 
|  |  | 
|  | if (result == NULL) { | 
|  | if (Compiler->emitFunctionName()) { | 
|  | vmkit::ThreadAllocator allocator; | 
|  | char* buf = GetMethodName( | 
|  | allocator, methodDef, customizing ? customizeFor : NULL); | 
|  | result = Function::Create(getFunctionType(), | 
|  | GlobalValue::ExternalWeakLinkage, buf, | 
|  | Compiler->getLLVMModule()); | 
|  | } else { | 
|  | result = Function::Create(getFunctionType(), | 
|  | GlobalValue::ExternalWeakLinkage, | 
|  | "", Compiler->getLLVMModule()); | 
|  | } | 
|  |  | 
|  | result->setGC("vmkit"); | 
|  | if (Compiler->useCooperativeGC()) { | 
|  | result->addFnAttr(Attribute::NoInline); | 
|  | } | 
|  | result->addFnAttr(Attribute::NoUnwind); | 
|  |  | 
|  | Compiler->functions.insert(std::make_pair(result, methodDef)); | 
|  | if (!Compiler->isStaticCompiling() && !customizing && methodDef->code) { | 
|  | Compiler->setMethod(result, methodDef->code, result->getName().data()); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (customizing) { | 
|  | customizedVersions[customizeFor] = result; | 
|  | } else { | 
|  | methodFunction = result; | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | FunctionType* LLVMMethodInfo::getFunctionType() { | 
|  | if (!functionType) { | 
|  | Signdef* sign = methodDef->getSignature(); | 
|  | LLVMSignatureInfo* LSI = Compiler->getSignatureInfo(sign); | 
|  | assert(LSI); | 
|  | if (isStatic(methodDef->access)) { | 
|  | functionType = LSI->getStaticType(); | 
|  | } else { | 
|  | functionType = LSI->getVirtualType(); | 
|  | } | 
|  | } | 
|  | return functionType; | 
|  | } | 
|  |  | 
|  | Constant* LLVMMethodInfo::getOffset() { | 
|  | if (!offsetConstant) { | 
|  | LLVMContext& context = Compiler->getLLVMModule()->getContext(); | 
|  |  | 
|  | Compiler->resolveVirtualClass(methodDef->classDef); | 
|  | offsetConstant = ConstantInt::get(Type::getInt32Ty(context), | 
|  | methodDef->offset); | 
|  | } | 
|  | return offsetConstant; | 
|  | } | 
|  |  | 
|  | Constant* LLVMFieldInfo::getOffset() { | 
|  | if (!offsetConstant) { | 
|  | LLVMContext& context = Compiler->getLLVMModule()->getContext(); | 
|  |  | 
|  | if (isStatic(fieldDef->access)) { | 
|  | Compiler->resolveStaticClass(fieldDef->classDef); | 
|  | } else { | 
|  | Compiler->resolveVirtualClass(fieldDef->classDef); | 
|  | } | 
|  |  | 
|  | offsetConstant = ConstantInt::get(Type::getInt32Ty(context), fieldDef->num); | 
|  | } | 
|  | return offsetConstant; | 
|  | } | 
|  |  | 
|  | llvm::FunctionType* LLVMSignatureInfo::getVirtualType() { | 
|  | if (!virtualType) { | 
|  | // Lock here because we are called by arbitrary code | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | std::vector<llvm::Type*> llvmArgs; | 
|  | uint32 size = signature->nbArguments; | 
|  | Typedef* const* arguments = signature->getArgumentsType(); | 
|  |  | 
|  | llvmArgs.push_back(Compiler->getIntrinsics()->JavaObjectType); | 
|  |  | 
|  | for (uint32 i = 0; i < size; ++i) { | 
|  | Typedef* type = arguments[i]; | 
|  | LLVMAssessorInfo& LAI = Compiler->getTypedefInfo(type); | 
|  | llvmArgs.push_back(LAI.llvmType); | 
|  | } | 
|  |  | 
|  | LLVMAssessorInfo& LAI = | 
|  | Compiler->getTypedefInfo(signature->getReturnType()); | 
|  | virtualType = FunctionType::get(LAI.llvmType, llvmArgs, false); | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | } | 
|  | return virtualType; | 
|  | } | 
|  |  | 
|  | llvm::FunctionType* LLVMSignatureInfo::getStaticType() { | 
|  | if (!staticType) { | 
|  | // Lock here because we are called by arbitrary code | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | std::vector<llvm::Type*> llvmArgs; | 
|  | uint32 size = signature->nbArguments; | 
|  | Typedef* const* arguments = signature->getArgumentsType(); | 
|  |  | 
|  | for (uint32 i = 0; i < size; ++i) { | 
|  | Typedef* type = arguments[i]; | 
|  | LLVMAssessorInfo& LAI = Compiler->getTypedefInfo(type); | 
|  | llvmArgs.push_back(LAI.llvmType); | 
|  | } | 
|  |  | 
|  | LLVMAssessorInfo& LAI = | 
|  | Compiler->getTypedefInfo(signature->getReturnType()); | 
|  | staticType = FunctionType::get(LAI.llvmType, llvmArgs, false); | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | } | 
|  | return staticType; | 
|  | } | 
|  |  | 
|  | llvm::FunctionType* LLVMSignatureInfo::getNativeType() { | 
|  | if (!nativeType) { | 
|  | // Lock here because we are called by arbitrary code | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | std::vector<llvm::Type*> llvmArgs; | 
|  | uint32 size = signature->nbArguments; | 
|  | Typedef* const* arguments = signature->getArgumentsType(); | 
|  |  | 
|  | llvm::Type* Ty = | 
|  | PointerType::getUnqual(Compiler->getIntrinsics()->JavaObjectType); | 
|  |  | 
|  | llvmArgs.push_back(Compiler->getIntrinsics()->ptrType); // JNIEnv | 
|  | llvmArgs.push_back(Ty); // Class | 
|  |  | 
|  | for (uint32 i = 0; i < size; ++i) { | 
|  | Typedef* type = arguments[i]; | 
|  | LLVMAssessorInfo& LAI = Compiler->getTypedefInfo(type); | 
|  | llvm::Type* Ty = LAI.llvmType; | 
|  | if (Ty == Compiler->getIntrinsics()->JavaObjectType) { | 
|  | llvmArgs.push_back(LAI.llvmTypePtr); | 
|  | } else { | 
|  | llvmArgs.push_back(LAI.llvmType); | 
|  | } | 
|  | } | 
|  |  | 
|  | LLVMAssessorInfo& LAI = | 
|  | Compiler->getTypedefInfo(signature->getReturnType()); | 
|  | llvm::Type* RetType = | 
|  | LAI.llvmType == Compiler->getIntrinsics()->JavaObjectType ? | 
|  | LAI.llvmTypePtr : LAI.llvmType; | 
|  | nativeType = FunctionType::get(RetType, llvmArgs, false); | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | } | 
|  | return nativeType; | 
|  | } | 
|  |  | 
|  | llvm::FunctionType* LLVMSignatureInfo::getNativeStubType() { | 
|  | // Lock here because we are called by arbitrary code | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | std::vector<llvm::Type*> llvmArgs; | 
|  | uint32 size = signature->nbArguments; | 
|  | Typedef* const* arguments = signature->getArgumentsType(); | 
|  |  | 
|  | llvm::Type* Ty = | 
|  | PointerType::getUnqual(Compiler->getIntrinsics()->JavaObjectType); | 
|  |  | 
|  | llvmArgs.push_back(PointerType::getUnqual(getNativeType())); // method | 
|  | llvmArgs.push_back(Compiler->getIntrinsics()->ptrType); // JNIEnv | 
|  | llvmArgs.push_back(Ty); // Class | 
|  |  | 
|  | for (uint32 i = 0; i < size; ++i) { | 
|  | Typedef* type = arguments[i]; | 
|  | LLVMAssessorInfo& LAI = Compiler->getTypedefInfo(type); | 
|  | llvm::Type* Ty = LAI.llvmType; | 
|  | if (Ty == Compiler->getIntrinsics()->JavaObjectType) { | 
|  | llvmArgs.push_back(LAI.llvmTypePtr); | 
|  | } else { | 
|  | llvmArgs.push_back(LAI.llvmType); | 
|  | } | 
|  | } | 
|  |  | 
|  | LLVMAssessorInfo& LAI = | 
|  | Compiler->getTypedefInfo(signature->getReturnType()); | 
|  | llvm::Type* RetType = | 
|  | LAI.llvmType == Compiler->getIntrinsics()->JavaObjectType ? | 
|  | LAI.llvmTypePtr : LAI.llvmType; | 
|  | FunctionType* FTy = FunctionType::get(RetType, llvmArgs, false); | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | return FTy; | 
|  | } | 
|  |  | 
|  |  | 
|  | Function* LLVMSignatureInfo::createFunctionCallBuf(bool virt) { | 
|  |  | 
|  | std::vector<Value*> Args; | 
|  |  | 
|  | LLVMContext& context = Compiler->getLLVMModule()->getContext(); | 
|  | J3Intrinsics& Intrinsics = *Compiler->getIntrinsics(); | 
|  | Function* res = 0; | 
|  | FunctionType* FTy = virt ? getVirtualBufType() : getStaticBufType(); | 
|  | if (virt) { | 
|  | res = Compiler->virtualBufs[FTy]; | 
|  | } else { | 
|  | res = Compiler->staticBufs[FTy]; | 
|  | } | 
|  | if (res != NULL) { | 
|  | return res; | 
|  | } | 
|  | if (Compiler->isStaticCompiling()) { | 
|  | vmkit::ThreadAllocator allocator; | 
|  | const char* type = virt ? "virtual_buf" : "static_buf"; | 
|  | char* buf = (char*)allocator.Allocate( | 
|  | (signature->keyName->size << 1) + 1 + 11); | 
|  | signature->nativeName(buf, type); | 
|  | res = Function::Create( | 
|  | FTy, GlobalValue::ExternalLinkage, buf, Compiler->getLLVMModule()); | 
|  | } else { | 
|  | res = Function::Create( | 
|  | FTy, GlobalValue::ExternalLinkage, "", Compiler->getLLVMModule()); | 
|  | } | 
|  |  | 
|  | BasicBlock* currentBlock = BasicBlock::Create(context, "enter", res); | 
|  | Function::arg_iterator i = res->arg_begin(); | 
|  | Value *obj, *ptr, *func; | 
|  | ++i; | 
|  | func = i; | 
|  | func->setName("func"); | 
|  | ++i; | 
|  | if (virt) { | 
|  | obj = i; | 
|  | ++i; | 
|  | Args.push_back(obj); | 
|  | obj->setName("object"); | 
|  | } | 
|  | ptr = i; | 
|  | ptr->setName("nextArgPtr"); | 
|  |  | 
|  | Typedef* const* arguments = signature->getArgumentsType(); | 
|  | for (uint32 i = 0; i < signature->nbArguments; ++i) { | 
|  |  | 
|  | LLVMAssessorInfo& LAI = Compiler->getTypedefInfo(arguments[i]); | 
|  | Value* arg = new LoadInst(ptr, "loadedArg", currentBlock); | 
|  |  | 
|  | if (arguments[i]->isReference()) { | 
|  | arg = new IntToPtrInst(arg, Intrinsics.JavaObjectType, "", currentBlock); | 
|  | Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, | 
|  | Intrinsics.JavaObjectNullConstant, | 
|  | arg, "isNullRefArg"); | 
|  | BasicBlock* endBlock = BasicBlock::Create(context, "refArgDone", res); | 
|  | BasicBlock* loadBlock = BasicBlock::Create(context, "loadRefArg", res); | 
|  | PHINode* node = PHINode::Create(Intrinsics.JavaObjectType, 2, "refArg", | 
|  | endBlock); | 
|  | node->addIncoming(Intrinsics.JavaObjectNullConstant, currentBlock); | 
|  | BranchInst::Create(endBlock, loadBlock, cmp, currentBlock); | 
|  | currentBlock = loadBlock; | 
|  | arg = new BitCastInst(arg, | 
|  | PointerType::getUnqual(Intrinsics.JavaObjectType), | 
|  | "", currentBlock); | 
|  | arg = new LoadInst(arg, "loadedRefArg", false, currentBlock); | 
|  | node->addIncoming(arg, currentBlock); | 
|  | BranchInst::Create(endBlock, currentBlock); | 
|  | currentBlock = endBlock; | 
|  | arg = node; | 
|  | } else if (arguments[i]->isFloat()) { | 
|  | arg = new TruncInst(arg, Compiler->AssessorInfo[I_INT].llvmType, | 
|  | "", currentBlock); | 
|  | arg = new BitCastInst(arg, LAI.llvmType, "arg", currentBlock); | 
|  | } else if (arguments[i]->isDouble()) { | 
|  | arg = new BitCastInst(arg, LAI.llvmType, "arg", currentBlock); | 
|  | } else if (!arguments[i]->isLong()){ | 
|  | arg = new TruncInst(arg, LAI.llvmType, "arg", currentBlock); | 
|  | } | 
|  | Args.push_back(arg); | 
|  | ptr = GetElementPtrInst::Create(ptr, Intrinsics.constantOne,"nextArgPtr", | 
|  | currentBlock); | 
|  | } | 
|  |  | 
|  | Value* val = CallInst::Create(func, Args, signature->getReturnType()->isVoid() ? "" : "retVal", currentBlock); | 
|  | if (!signature->getReturnType()->isVoid()) { | 
|  | ReturnInst::Create(context, val, currentBlock); | 
|  | } else { | 
|  | ReturnInst::Create(context, currentBlock); | 
|  | } | 
|  |  | 
|  | res->setGC("vmkit"); | 
|  | res->addFnAttr(Attribute::NoInline); | 
|  | res->addFnAttr(Attribute::NoUnwind); | 
|  |  | 
|  | if (virt) { | 
|  | Compiler->virtualBufs[FTy] = res; | 
|  | } else { | 
|  | Compiler->staticBufs[FTy] = res; | 
|  | } | 
|  |  | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Function* LLVMSignatureInfo::createFunctionCallAP(bool virt) { | 
|  |  | 
|  | std::vector<Value*> Args; | 
|  |  | 
|  | J3Intrinsics& Intrinsics = *Compiler->getIntrinsics(); | 
|  | Function* res = NULL; | 
|  | FunctionType* FTy = virt ? getVirtualBufType() : getStaticBufType(); | 
|  | if (virt) { | 
|  | res = Compiler->virtualAPs[FTy]; | 
|  | } else { | 
|  | res = Compiler->staticAPs[FTy]; | 
|  | } | 
|  | if (res != NULL) { | 
|  | return res; | 
|  | } | 
|  | if (Compiler->isStaticCompiling()) { | 
|  | vmkit::ThreadAllocator allocator; | 
|  | const char* type = virt ? "virtual_ap" : "static_ap"; | 
|  | char* buf = (char*)allocator.Allocate( | 
|  | (signature->keyName->size << 1) + 1 + 11); | 
|  | signature->nativeName(buf, type); | 
|  | res = Function::Create( | 
|  | FTy, GlobalValue::ExternalLinkage, buf, Compiler->getLLVMModule()); | 
|  | } else { | 
|  | res = Function::Create( | 
|  | FTy, GlobalValue::ExternalLinkage, "", Compiler->getLLVMModule()); | 
|  | } | 
|  | LLVMContext& context = Compiler->getLLVMModule()->getContext(); | 
|  |  | 
|  | BasicBlock* currentBlock = BasicBlock::Create(context, "enter", res); | 
|  | Function::arg_iterator i = res->arg_begin(); | 
|  | Value *obj, *ap, *func; | 
|  | ++i; | 
|  | func = i; | 
|  | ++i; | 
|  | if (virt) { | 
|  | obj = i; | 
|  | Args.push_back(obj); | 
|  | ++i; | 
|  | } | 
|  | ap = i; | 
|  |  | 
|  | Typedef* const* arguments = signature->getArgumentsType(); | 
|  | for (uint32 i = 0; i < signature->nbArguments; ++i) { | 
|  | LLVMAssessorInfo& LAI = Compiler->getTypedefInfo(arguments[i]); | 
|  | Value* arg = new VAArgInst(ap, LAI.llvmType, "", currentBlock); | 
|  | if (arguments[i]->isReference()) { | 
|  | arg = new IntToPtrInst(arg, Intrinsics.JavaObjectType, "", currentBlock); | 
|  | Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, | 
|  | Intrinsics.JavaObjectNullConstant, | 
|  | arg, ""); | 
|  | BasicBlock* endBlock = BasicBlock::Create(context, "end", res); | 
|  | BasicBlock* loadBlock = BasicBlock::Create(context, "load", res); | 
|  | PHINode* node = PHINode::Create(Intrinsics.JavaObjectType, 2, "", | 
|  | endBlock); | 
|  | node->addIncoming(Intrinsics.JavaObjectNullConstant, currentBlock); | 
|  | BranchInst::Create(endBlock, loadBlock, cmp, currentBlock); | 
|  | currentBlock = loadBlock; | 
|  | arg = new BitCastInst(arg, | 
|  | PointerType::getUnqual(Intrinsics.JavaObjectType), | 
|  | "", currentBlock); | 
|  | arg = new LoadInst(arg, "", false, currentBlock); | 
|  | node->addIncoming(arg, currentBlock); | 
|  | BranchInst::Create(endBlock, currentBlock); | 
|  | currentBlock = endBlock; | 
|  | arg = node; | 
|  | } | 
|  | Args.push_back(arg); | 
|  | } | 
|  |  | 
|  | Value* val = CallInst::Create(func, Args, "", currentBlock); | 
|  | if (!signature->getReturnType()->isVoid()) { | 
|  | ReturnInst::Create(context, val, currentBlock); | 
|  | } else { | 
|  | ReturnInst::Create(context, currentBlock); | 
|  | } | 
|  |  | 
|  | res->setGC("vmkit"); | 
|  | res->addFnAttr(Attribute::NoInline); | 
|  | res->addFnAttr(Attribute::NoUnwind); | 
|  |  | 
|  | if (virt) { | 
|  | Compiler->virtualAPs[FTy] = res; | 
|  | } else { | 
|  | Compiler->staticAPs[FTy] = res; | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | Function* LLVMSignatureInfo::createFunctionStub(bool special, bool virt) { | 
|  |  | 
|  | std::vector<Value*> Args; | 
|  | std::vector<Value*> FunctionArgs; | 
|  | std::vector<Value*> TempArgs; | 
|  |  | 
|  | J3Intrinsics& Intrinsics = *Compiler->getIntrinsics(); | 
|  | Function* stub = NULL; | 
|  | FunctionType* FTy = (virt || special)? getVirtualType() : getStaticType(); | 
|  | if (virt) { | 
|  | stub = Compiler->virtualStubs[FTy]; | 
|  | } else if (special) { | 
|  | stub = Compiler->specialStubs[FTy]; | 
|  | } else { | 
|  | stub = Compiler->staticStubs[FTy]; | 
|  | } | 
|  | if (stub != NULL) { | 
|  | return stub; | 
|  | } | 
|  | if (Compiler->isStaticCompiling()) { | 
|  | vmkit::ThreadAllocator allocator; | 
|  | const char* type = virt ? "virtual_stub" : special ? "special_stub" : "static_stub"; | 
|  | char* buf = (char*)allocator.Allocate( | 
|  | (signature->keyName->size << 1) + 1 + 11); | 
|  | signature->nativeName(buf, type); | 
|  | stub = Function::Create( | 
|  | FTy, GlobalValue::ExternalLinkage, buf, Compiler->getLLVMModule()); | 
|  |  | 
|  |  | 
|  | } else { | 
|  | stub = Function::Create( | 
|  | FTy, GlobalValue::ExternalLinkage, "", Compiler->getLLVMModule()); | 
|  | } | 
|  | LLVMContext& context = Compiler->getLLVMModule()->getContext(); | 
|  |  | 
|  | BasicBlock* currentBlock = BasicBlock::Create(context, "enter", stub); | 
|  | BasicBlock* endBlock = BasicBlock::Create(context, "end", stub); | 
|  | BasicBlock* callBlock = BasicBlock::Create(context, "call", stub); | 
|  | PHINode* node = NULL; | 
|  | if (!signature->getReturnType()->isVoid()) { | 
|  | node = PHINode::Create(stub->getReturnType(), 2, "retVal", endBlock); | 
|  | } | 
|  |  | 
|  |  | 
|  | for (Function::arg_iterator arg = stub->arg_begin(); | 
|  | arg != stub->arg_end(); ++arg) { | 
|  | Value* temp = arg; | 
|  | if (Compiler->useCooperativeGC() && | 
|  | arg->getType() == Intrinsics.JavaObjectType) { | 
|  | temp = new AllocaInst(Intrinsics.JavaObjectType, "arg", currentBlock); | 
|  | new StoreInst(arg, temp, "", currentBlock); | 
|  | Value* GCArgs[2] = { | 
|  | new BitCastInst(temp, Intrinsics.ptrPtrType, "", currentBlock), | 
|  | Intrinsics.constantPtrNull | 
|  | }; | 
|  |  | 
|  | CallInst::Create(Intrinsics.llvm_gc_gcroot, GCArgs, "", currentBlock); | 
|  | } else | 
|  | arg->setName("arg"); | 
|  |  | 
|  | TempArgs.push_back(temp); | 
|  | } | 
|  |  | 
|  | if (virt) { | 
|  | if (Compiler->useCooperativeGC()) { | 
|  | Args.push_back(new LoadInst(TempArgs[0], "object", false, currentBlock)); | 
|  | } else { | 
|  | TempArgs[0]->setName("object"); | 
|  | Args.push_back(TempArgs[0]); | 
|  | } | 
|  | } | 
|  |  | 
|  | Value* val = CallInst::Create(virt ? Intrinsics.ResolveVirtualStubFunction : | 
|  | special ? Intrinsics.ResolveSpecialStubFunction: | 
|  | Intrinsics.ResolveStaticStubFunction, | 
|  | Args, "resolvedFuncPtr", currentBlock); | 
|  |  | 
|  | Constant* nullValue = Constant::getNullValue(val->getType()); | 
|  | Value* cmp = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, | 
|  | nullValue, val, "isNotResolved"); | 
|  | BranchInst::Create(endBlock, callBlock, cmp, currentBlock); | 
|  | if (node) node->addIncoming(Constant::getNullValue(node->getType()), | 
|  | currentBlock); | 
|  |  | 
|  | currentBlock = callBlock; | 
|  | Value* Func = new BitCastInst(val, stub->getType(), "resolvedFunc", currentBlock); | 
|  |  | 
|  | int i = 0; | 
|  | for (Function::arg_iterator arg = stub->arg_begin(); | 
|  | arg != stub->arg_end(); ++arg, ++i) { | 
|  | Value* temp = arg; | 
|  | if (Compiler->useCooperativeGC() && | 
|  | arg->getType() == Intrinsics.JavaObjectType) { | 
|  | temp = new LoadInst(TempArgs[i], "arg", false, currentBlock); | 
|  | } else | 
|  | temp->setName("arg"); | 
|  | FunctionArgs.push_back(temp); | 
|  | } | 
|  | Value* res = CallInst::Create(Func, FunctionArgs, node ? "funcRetVal" : "", currentBlock); | 
|  | if (node) node->addIncoming(res, currentBlock); | 
|  | BranchInst::Create(endBlock, currentBlock); | 
|  |  | 
|  | currentBlock = endBlock; | 
|  | if (node) { | 
|  | ReturnInst::Create(context, node, currentBlock); | 
|  | } else { | 
|  | ReturnInst::Create(context, currentBlock); | 
|  | } | 
|  |  | 
|  | stub->setGC("vmkit"); | 
|  | stub->addFnAttr(Attribute::NoInline); | 
|  | stub->addFnAttr(Attribute::NoUnwind); | 
|  |  | 
|  | if (virt) { | 
|  | Compiler->virtualStubs[FTy] = stub; | 
|  | } else if (special) { | 
|  | Compiler->specialStubs[FTy] = stub; | 
|  | } else { | 
|  | Compiler->staticStubs[FTy] = stub; | 
|  | } | 
|  | return stub; | 
|  | } | 
|  |  | 
|  | PointerType* LLVMSignatureInfo::getStaticPtrType() { | 
|  | if (!staticPtrType) { | 
|  | staticPtrType = PointerType::getUnqual(getStaticType()); | 
|  | } | 
|  | return staticPtrType; | 
|  | } | 
|  |  | 
|  | PointerType* LLVMSignatureInfo::getVirtualPtrType() { | 
|  | if (!virtualPtrType) { | 
|  | virtualPtrType = PointerType::getUnqual(getVirtualType()); | 
|  | } | 
|  | return virtualPtrType; | 
|  | } | 
|  |  | 
|  | PointerType* LLVMSignatureInfo::getNativePtrType() { | 
|  | if (!nativePtrType) { | 
|  | nativePtrType = PointerType::getUnqual(getNativeType()); | 
|  | } | 
|  | return nativePtrType; | 
|  | } | 
|  |  | 
|  |  | 
|  | FunctionType* LLVMSignatureInfo::getVirtualBufType() { | 
|  | if (!virtualBufType) { | 
|  | // Lock here because we are called by arbitrary code | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | std::vector<llvm::Type*> Args; | 
|  | Args.push_back(Compiler->getIntrinsics()->ResolvedConstantPoolType); // ctp | 
|  | Args.push_back(getVirtualPtrType()); | 
|  | Args.push_back(Compiler->getIntrinsics()->JavaObjectType); | 
|  | Args.push_back(Compiler->AssessorInfo[I_LONG].llvmTypePtr); | 
|  | LLVMAssessorInfo& LAI = | 
|  | Compiler->getTypedefInfo(signature->getReturnType()); | 
|  | virtualBufType = FunctionType::get(LAI.llvmType, Args, false); | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | } | 
|  | return virtualBufType; | 
|  | } | 
|  |  | 
|  | FunctionType* LLVMSignatureInfo::getStaticBufType() { | 
|  | if (!staticBufType) { | 
|  | // Lock here because we are called by arbitrary code | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | std::vector<llvm::Type*> Args; | 
|  | Args.push_back(Compiler->getIntrinsics()->ResolvedConstantPoolType); // ctp | 
|  | Args.push_back(getStaticPtrType()); | 
|  | Args.push_back(Compiler->AssessorInfo[I_LONG].llvmTypePtr); | 
|  | LLVMAssessorInfo& LAI = | 
|  | Compiler->getTypedefInfo(signature->getReturnType()); | 
|  | staticBufType = FunctionType::get(LAI.llvmType, Args, false); | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | } | 
|  | return staticBufType; | 
|  | } | 
|  |  | 
|  | Function* LLVMSignatureInfo::getVirtualBuf() { | 
|  | // Lock here because we are called by arbitrary code. Also put that here | 
|  | // because we are waiting on virtualBufFunction to have an address. | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | if (!virtualBufFunction) { | 
|  | virtualBufFunction = createFunctionCallBuf(true); | 
|  | signature->setVirtualCallBuf(Compiler->GenerateStub(virtualBufFunction)); | 
|  | } | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | return virtualBufFunction; | 
|  | } | 
|  |  | 
|  | Function* LLVMSignatureInfo::getVirtualAP() { | 
|  | // Lock here because we are called by arbitrary code. Also put that here | 
|  | // because we are waiting on virtualAPFunction to have an address. | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | if (!virtualAPFunction) { | 
|  | virtualAPFunction = createFunctionCallAP(true); | 
|  | signature->setVirtualCallAP(Compiler->GenerateStub(virtualAPFunction)); | 
|  | } | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | return virtualAPFunction; | 
|  | } | 
|  |  | 
|  | Function* LLVMSignatureInfo::getStaticBuf() { | 
|  | // Lock here because we are called by arbitrary code. Also put that here | 
|  | // because we are waiting on staticBufFunction to have an address. | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | if (!staticBufFunction) { | 
|  | staticBufFunction = createFunctionCallBuf(false); | 
|  | signature->setStaticCallBuf(Compiler->GenerateStub(staticBufFunction)); | 
|  | } | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | return staticBufFunction; | 
|  | } | 
|  |  | 
|  | Function* LLVMSignatureInfo::getStaticAP() { | 
|  | // Lock here because we are called by arbitrary code. Also put that here | 
|  | // because we are waiting on staticAPFunction to have an address. | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | if (!staticAPFunction) { | 
|  | staticAPFunction = createFunctionCallAP(false); | 
|  | signature->setStaticCallAP(Compiler->GenerateStub(staticAPFunction)); | 
|  | } | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | return staticAPFunction; | 
|  | } | 
|  |  | 
|  | Function* LLVMSignatureInfo::getStaticStub() { | 
|  | // Lock here because we are called by arbitrary code. Also put that here | 
|  | // because we are waiting on staticStubFunction to have an address. | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | if (!staticStubFunction) { | 
|  | staticStubFunction = createFunctionStub(false, false); | 
|  | signature->setStaticCallStub(Compiler->GenerateStub(staticStubFunction)); | 
|  | } | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | return staticStubFunction; | 
|  | } | 
|  |  | 
|  | Function* LLVMSignatureInfo::getSpecialStub() { | 
|  | // Lock here because we are called by arbitrary code. Also put that here | 
|  | // because we are waiting on specialStubFunction to have an address. | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | if (!specialStubFunction) { | 
|  | specialStubFunction = createFunctionStub(true, false); | 
|  | signature->setSpecialCallStub(Compiler->GenerateStub(specialStubFunction)); | 
|  | } | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | return specialStubFunction; | 
|  | } | 
|  |  | 
|  | Function* LLVMSignatureInfo::getVirtualStub() { | 
|  | // Lock here because we are called by arbitrary code. Also put that here | 
|  | // because we are waiting on virtualStubFunction to have an address. | 
|  | vmkit::VmkitModule::protectIR(); | 
|  | if (!virtualStubFunction) { | 
|  | virtualStubFunction = createFunctionStub(false, true); | 
|  | signature->setVirtualCallStub(Compiler->GenerateStub(virtualStubFunction)); | 
|  | } | 
|  | vmkit::VmkitModule::unprotectIR(); | 
|  | return virtualStubFunction; | 
|  | } | 
|  |  | 
|  | void JavaLLVMCompiler::initialiseAssessorInfo() { | 
|  | AssessorInfo[I_VOID].llvmType = Type::getVoidTy(getLLVMContext()); | 
|  | AssessorInfo[I_VOID].llvmTypePtr = 0; | 
|  | AssessorInfo[I_VOID].logSizeInBytesConstant = 0; | 
|  |  | 
|  | AssessorInfo[I_BOOL].llvmType = Type::getInt8Ty(getLLVMContext()); | 
|  | AssessorInfo[I_BOOL].llvmTypePtr = | 
|  | PointerType::getUnqual(Type::getInt8Ty(getLLVMContext())); | 
|  | AssessorInfo[I_BOOL].logSizeInBytesConstant = 0; | 
|  |  | 
|  | AssessorInfo[I_BYTE].llvmType = Type::getInt8Ty(getLLVMContext()); | 
|  | AssessorInfo[I_BYTE].llvmTypePtr = | 
|  | PointerType::getUnqual(Type::getInt8Ty(getLLVMContext())); | 
|  | AssessorInfo[I_BYTE].logSizeInBytesConstant = 0; | 
|  |  | 
|  | AssessorInfo[I_SHORT].llvmType = Type::getInt16Ty(getLLVMContext()); | 
|  | AssessorInfo[I_SHORT].llvmTypePtr = | 
|  | PointerType::getUnqual(Type::getInt16Ty(getLLVMContext())); | 
|  | AssessorInfo[I_SHORT].logSizeInBytesConstant = 1; | 
|  |  | 
|  | AssessorInfo[I_CHAR].llvmType = Type::getInt16Ty(getLLVMContext()); | 
|  | AssessorInfo[I_CHAR].llvmTypePtr = | 
|  | PointerType::getUnqual(Type::getInt16Ty(getLLVMContext())); | 
|  | AssessorInfo[I_CHAR].logSizeInBytesConstant = 1; | 
|  |  | 
|  | AssessorInfo[I_INT].llvmType = Type::getInt32Ty(getLLVMContext()); | 
|  | AssessorInfo[I_INT].llvmTypePtr = | 
|  | PointerType::getUnqual(Type::getInt32Ty(getLLVMContext())); | 
|  | AssessorInfo[I_INT].logSizeInBytesConstant = 2; | 
|  |  | 
|  | AssessorInfo[I_FLOAT].llvmType = Type::getFloatTy(getLLVMContext()); | 
|  | AssessorInfo[I_FLOAT].llvmTypePtr = | 
|  | PointerType::getUnqual(Type::getFloatTy(getLLVMContext())); | 
|  | AssessorInfo[I_FLOAT].logSizeInBytesConstant = 2; | 
|  |  | 
|  | AssessorInfo[I_LONG].llvmType = Type::getInt64Ty(getLLVMContext()); | 
|  | AssessorInfo[I_LONG].llvmTypePtr = | 
|  | PointerType::getUnqual(Type::getInt64Ty(getLLVMContext())); | 
|  | AssessorInfo[I_LONG].logSizeInBytesConstant = 3; | 
|  |  | 
|  | AssessorInfo[I_DOUBLE].llvmType = Type::getDoubleTy(getLLVMContext()); | 
|  | AssessorInfo[I_DOUBLE].llvmTypePtr = | 
|  | PointerType::getUnqual(Type::getDoubleTy(getLLVMContext())); | 
|  | AssessorInfo[I_DOUBLE].logSizeInBytesConstant = 3; | 
|  |  | 
|  | AssessorInfo[I_TAB].llvmType = JavaIntrinsics.JavaObjectType; | 
|  | AssessorInfo[I_TAB].llvmTypePtr = | 
|  | PointerType::getUnqual(AssessorInfo[I_TAB].llvmType); | 
|  | AssessorInfo[I_TAB].logSizeInBytesConstant = sizeof(JavaObject*) == 8 ? 3 : 2; | 
|  |  | 
|  | AssessorInfo[I_REF].llvmType = AssessorInfo[I_TAB].llvmType; | 
|  | AssessorInfo[I_REF].llvmTypePtr = AssessorInfo[I_TAB].llvmTypePtr; | 
|  | AssessorInfo[I_REF].logSizeInBytesConstant = sizeof(JavaObject*) == 8 ? 3 : 2; | 
|  | } | 
|  |  | 
|  | LLVMAssessorInfo& JavaLLVMCompiler::getTypedefInfo(const Typedef* type) { | 
|  | return AssessorInfo[type->getKey()->elements[0]]; | 
|  | } |