| //===----- LowerConstantCalls.cpp - Changes arrayLength calls --------------===// |
| // |
| // JnJVM |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| |
| #include "llvm/Pass.h" |
| #include "llvm/Function.h" |
| #include "llvm/Instructions.h" |
| #include "llvm/Support/CallSite.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/Debug.h" |
| |
| #include "mvm/JIT.h" |
| |
| #include "JnjvmModule.h" |
| |
| using namespace llvm; |
| |
| namespace jnjvm { |
| |
| class VISIBILITY_HIDDEN LowerConstantCalls : public FunctionPass { |
| public: |
| static char ID; |
| LowerConstantCalls() : FunctionPass((intptr_t)&ID) { } |
| |
| virtual bool runOnFunction(Function &F); |
| private: |
| }; |
| char LowerConstantCalls::ID = 0; |
| static RegisterPass<LowerConstantCalls> X("LowerConstantCalls", |
| "Lower Constant calls"); |
| |
| |
| static ConstantExpr* getClass(JnjvmModule* Mod, CallSite& Call) { |
| ConstantExpr* CE = 0; |
| if (Mod->isStaticCompiling()) { |
| LoadInst* LI = dyn_cast<LoadInst>(Call.getArgument(0)); |
| if (!LI) { |
| PHINode* node = dyn_cast<PHINode>(Call.getArgument(0)); |
| if (node) { |
| LI = dyn_cast<LoadInst>(node->getIncomingValue(0)); |
| } |
| } |
| |
| if (LI) { |
| GlobalVariable* GV = dyn_cast<GlobalVariable>(LI->getOperand(0)); |
| CE = dyn_cast<ConstantExpr>(GV->getInitializer()); |
| } |
| } else { |
| CE = dyn_cast<ConstantExpr>(Call.getArgument(0)); |
| if (!CE) { |
| // It has to be a phi for intialization check. |
| PHINode* node = dyn_cast<PHINode>(Call.getArgument(0)); |
| if (node) CE = dyn_cast<ConstantExpr>(node->getIncomingValue(0)); |
| } |
| } |
| return CE; |
| } |
| |
| #ifdef ISOLATE |
| static Value* getTCM(JnjvmModule* module, Value* Arg, Instruction* CI) { |
| Value* GEP[2] = { module->constantZero, |
| module->OffsetTaskClassMirrorInClassConstant }; |
| Value* TCMArray = GetElementPtrInst::Create(Arg, GEP, GEP + 2, "", CI); |
| |
| Value* threadId = CallInst::Create(module->llvm_frameaddress, |
| module->constantZero, "", CI); |
| threadId = new PtrToIntInst(threadId, module->pointerSizeType, "", CI); |
| threadId = BinaryOperator::CreateAnd(threadId, module->constantThreadIDMask, |
| "", CI); |
| |
| threadId = new IntToPtrInst(threadId, module->ptr32Type, "", CI); |
| |
| Value* IsolateID = GetElementPtrInst::Create(threadId, module->constantThree, |
| "", CI); |
| IsolateID = new LoadInst(IsolateID, "", CI); |
| |
| Value* GEP2[2] = { module->constantZero, IsolateID }; |
| |
| Value* TCM = GetElementPtrInst::Create(TCMArray, GEP2, GEP2 + 2, "", |
| CI); |
| return TCM; |
| } |
| #else |
| static Value* getTCM(JnjvmModule* module, Value* Arg, Instruction* CI) { |
| Value* GEP[2] = { module->constantZero, |
| module->OffsetTaskClassMirrorInClassConstant }; |
| Value* TCMArray = GetElementPtrInst::Create(Arg, GEP, GEP + 2, "", CI); |
| |
| Value* GEP2[2] = { module->constantZero, module->constantZero }; |
| |
| Value* TCM = GetElementPtrInst::Create(TCMArray, GEP2, GEP2 + 2, "", |
| CI); |
| return TCM; |
| |
| } |
| #endif |
| |
| #ifdef ISOLATE |
| static Value* getDelegatee(JnjvmModule* module, Value* Arg, Instruction* CI) { |
| Value* GEP[2] = { module->constantZero, |
| module->constantTwo }; |
| Value* TCMArray = GetElementPtrInst::Create(Arg, GEP, GEP + 2, "", CI); |
| |
| Value* threadId = CallInst::Create(module->llvm_frameaddress, |
| module->constantZero, "", CI); |
| threadId = new PtrToIntInst(threadId, module->pointerSizeType, "", CI); |
| threadId = BinaryOperator::CreateAnd(threadId, module->constantThreadIDMask, |
| "", CI); |
| |
| threadId = new IntToPtrInst(threadId, module->ptr32Type, "", CI); |
| |
| Value* IsolateID = GetElementPtrInst::Create(threadId, module->constantThree, |
| "", CI); |
| IsolateID = new LoadInst(IsolateID, "", CI); |
| |
| Value* GEP2[2] = { module->constantZero, IsolateID }; |
| |
| Value* TCM = GetElementPtrInst::Create(TCMArray, GEP2, GEP2 + 2, "", |
| CI); |
| return new LoadInst(TCM, "", CI); |
| } |
| #else |
| static Value* getDelegatee(JnjvmModule* module, Value* Arg, Instruction* CI) { |
| Value* GEP[2] = { module->constantZero, |
| module->constantTwo }; |
| Value* TCMArray = GetElementPtrInst::Create(Arg, GEP, GEP + 2, "", CI); |
| |
| Value* GEP2[2] = { module->constantZero, module->constantZero }; |
| |
| Value* TCM = GetElementPtrInst::Create(TCMArray, GEP2, GEP2 + 2, "", |
| CI); |
| return new LoadInst(TCM, "", CI); |
| |
| } |
| #endif |
| |
| bool LowerConstantCalls::runOnFunction(Function& F) { |
| JnjvmModule* module = (JnjvmModule*)F.getParent(); |
| bool Changed = false; |
| for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) { |
| BasicBlock *Cur = BI; |
| for (BasicBlock::iterator II = Cur->begin(), IE = Cur->end(); II != IE;) { |
| Instruction *I = II; |
| II++; |
| CallSite Call = CallSite::get(I); |
| Instruction* CI = Call.getInstruction(); |
| if (CI) { |
| Value* V = Call.getCalledValue(); |
| if (V == module->ArrayLengthFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); // get the array |
| Value* array = new BitCastInst(val, module->JavaArrayType, |
| "", CI); |
| Value* args[2] = { module->constantZero, |
| module->JavaArraySizeOffsetConstant }; |
| Value* ptr = GetElementPtrInst::Create(array, args, args + 2, |
| "", CI); |
| Value* load = new LoadInst(ptr, "", CI); |
| load = new PtrToIntInst(load, Type::Int32Ty, "", CI); |
| CI->replaceAllUsesWith(load); |
| CI->eraseFromParent(); |
| } else if (V == module->GetVTFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); // get the object |
| Value* indexes[2] = { module->constantZero, module->constantZero }; |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes, indexes + 2, |
| "", CI); |
| Value* VT = new LoadInst(VTPtr, "", CI); |
| CI->replaceAllUsesWith(VT); |
| CI->eraseFromParent(); |
| } else if (V == module->GetClassFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); // get the object |
| Value* args2[2] = { module->constantZero, |
| module->JavaObjectClassOffsetConstant }; |
| Value* classPtr = GetElementPtrInst::Create(val, args2, args2 + 2, |
| "", CI); |
| Value* cl = new LoadInst(classPtr, "", CI); |
| CI->replaceAllUsesWith(cl); |
| CI->eraseFromParent(); |
| } else if (V == module->GetVTFromClassFunction) { |
| Changed = true; |
| |
| ConstantExpr* CE = getClass(module, Call); |
| if (CE) { |
| ConstantInt* C = (ConstantInt*)CE->getOperand(0); |
| Class* cl = (Class*)C->getZExtValue(); |
| if (cl->isResolved()) { |
| Value* VT = module->getVirtualTable(cl, CI); |
| CI->replaceAllUsesWith(VT); |
| CI->eraseFromParent(); |
| continue; |
| } |
| } |
| |
| Value* val = Call.getArgument(0); |
| Value* indexes[2] = { module->constantZero, |
| module->OffsetVTInClassConstant }; |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes, indexes + 2, |
| "", CI); |
| Value* VT = new LoadInst(VTPtr, "", CI); |
| CI->replaceAllUsesWith(VT); |
| CI->eraseFromParent(); |
| } else if (V == module->GetObjectSizeFromClassFunction) { |
| Changed = true; |
| |
| ConstantExpr* CE = getClass(module, Call); |
| if (CE) { |
| ConstantInt* C = (ConstantInt*)CE->getOperand(0); |
| Class* cl = (Class*)C->getZExtValue(); |
| if (cl->isResolved()) { |
| LLVMClassInfo* LCI = module->getClassInfo(cl); |
| Value* Size = LCI->getVirtualSize(); |
| CI->replaceAllUsesWith(Size); |
| CI->eraseFromParent(); |
| continue; |
| } |
| } |
| |
| Value* val = Call.getArgument(0); |
| Value* indexes[2] = { module->constantZero, |
| module->OffsetObjectSizeInClassConstant }; |
| Value* SizePtr = GetElementPtrInst::Create(val, indexes, indexes + 2, |
| "", CI); |
| Value* Size = new LoadInst(SizePtr, "", CI); |
| CI->replaceAllUsesWith(Size); |
| CI->eraseFromParent(); |
| } else if (V == module->GetDepthFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| Value* indexes[2] = { module->constantZero, |
| module->OffsetDepthInClassConstant }; |
| Value* DepthPtr = GetElementPtrInst::Create(val, indexes, |
| indexes + 2, "", CI); |
| Value* Depth = new LoadInst(DepthPtr, "", CI); |
| CI->replaceAllUsesWith(Depth); |
| CI->eraseFromParent(); |
| } else if (V == module->GetDisplayFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| Value* indexes[2] = { module->constantZero, |
| module->OffsetDisplayInClassConstant }; |
| Value* DisplayPtr = GetElementPtrInst::Create(val, indexes, |
| indexes + 2, "", CI); |
| Value* Display = new LoadInst(DisplayPtr, "", CI); |
| CI->replaceAllUsesWith(Display); |
| CI->eraseFromParent(); |
| } else if (V == module->GetClassInDisplayFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| Value* depth = Call.getArgument(1); |
| Value* ClassPtr = GetElementPtrInst::Create(val, depth, "", CI); |
| Value* Class = new LoadInst(ClassPtr, "", CI); |
| CI->replaceAllUsesWith(Class); |
| CI->eraseFromParent(); |
| } else if (V == module->InstanceOfFunction) { |
| ConstantExpr* CE = dyn_cast<ConstantExpr>(Call.getArgument(1)); |
| if (CE) { |
| ConstantInt* C = (ConstantInt*)CE->getOperand(0); |
| CommonClass* cl = (CommonClass*)C->getZExtValue(); |
| Changed = true; |
| BasicBlock* NBB = II->getParent()->splitBasicBlock(II); |
| I->getParent()->getTerminator()->eraseFromParent(); |
| Value* obj = Call.getArgument(0); |
| Instruction* cmp = new ICmpInst(ICmpInst::ICMP_EQ, obj, |
| module->JavaObjectNullConstant, |
| "", CI); |
| BasicBlock* ifTrue = BasicBlock::Create("", &F); |
| BasicBlock* ifFalse = BasicBlock::Create("", &F); |
| BranchInst::Create(ifTrue, ifFalse, cmp, CI); |
| PHINode* node = PHINode::Create(Type::Int1Ty, "", ifTrue); |
| node->addIncoming(ConstantInt::getFalse(), CI->getParent()); |
| Value* objCl = CallInst::Create(module->GetClassFunction, obj, |
| "", ifFalse); |
| |
| if (isInterface(cl->access)) { |
| Value* args[2] = { objCl, CE }; |
| Value* res = CallInst::Create(module->ImplementsFunction, |
| args, args + 2, "", ifFalse); |
| node->addIncoming(res, ifFalse); |
| BranchInst::Create(ifTrue, ifFalse); |
| } else { |
| cmp = new ICmpInst(ICmpInst::ICMP_EQ, objCl, CE, "", ifFalse); |
| BasicBlock* notEquals = BasicBlock::Create("", &F); |
| BranchInst::Create(ifTrue, notEquals, cmp, ifFalse); |
| node->addIncoming(ConstantInt::getTrue(), ifFalse); |
| |
| if (cl->isPrimitive()) { |
| fprintf(stderr, "implement me"); |
| abort(); |
| } else if (cl->isArray()) { |
| Value* args[2] = { objCl, CE }; |
| Value* res = |
| CallInst::Create(module->InstantiationOfArrayFunction, |
| args, args + 2, "", notEquals); |
| node->addIncoming(res, notEquals); |
| BranchInst::Create(ifTrue, notEquals); |
| } else { |
| Value* depthCl; |
| if (cl->asClass()->isResolved()) { |
| depthCl = ConstantInt::get(Type::Int32Ty, cl->depth); |
| } else { |
| depthCl = CallInst::Create(module->GetDepthFunction, |
| CE, "", notEquals); |
| } |
| Value* depthClObj = CallInst::Create(module->GetDepthFunction, |
| objCl, "", notEquals); |
| Value* cmp = new ICmpInst(ICmpInst::ICMP_ULE, depthCl, depthClObj, "", |
| notEquals); |
| |
| BasicBlock* supDepth = BasicBlock::Create("superior depth", &F); |
| |
| BranchInst::Create(supDepth, ifTrue, cmp, notEquals); |
| node->addIncoming(ConstantInt::getFalse(), notEquals); |
| |
| Value* inDisplay = |
| CallInst::Create(module->GetDisplayFunction, objCl, |
| "", supDepth); |
| |
| Value* args[2] = { inDisplay, depthCl }; |
| Value* clInDisplay = |
| CallInst::Create(module->GetClassInDisplayFunction, |
| args, args + 2, "", supDepth); |
| |
| cmp = new ICmpInst(ICmpInst::ICMP_EQ, clInDisplay, CE, "", |
| supDepth); |
| BranchInst::Create(ifTrue, supDepth); |
| node->addIncoming(cmp, supDepth); |
| } |
| } |
| CI->replaceAllUsesWith(node); |
| CI->eraseFromParent(); |
| BranchInst::Create(NBB, ifTrue); |
| break; |
| } |
| } else if (V == module->GetStaticInstanceFunction) { |
| Changed = true; |
| #if !defined(ISOLATE_SHARING) && !defined(ISOLATE) |
| ConstantExpr* CE = getClass(module, Call); |
| assert(CE && "Wrong use of GetStaticInstanceFunction"); |
| |
| ConstantInt* C = (ConstantInt*)CE->getOperand(0); |
| Class* cl = (Class*)C->getZExtValue(); |
| |
| Value* Replace = module->getStaticInstance(cl, CI); |
| CI->replaceAllUsesWith(Replace); |
| CI->eraseFromParent(); |
| |
| #elif defined(ISOLATE) |
| Value* TCM = getTCM(module, Call.getArgument(0), CI); |
| Constant* C = module->OffsetStaticInstanceInTaskClassMirrorConstant; |
| Value* GEP[2] = { module->constantZero, C }; |
| Value* Replace = GetElementPtrInst::Create(TCM, GEP, GEP + 2, "", CI); |
| Replace = new LoadInst(Replace, "", CI); |
| CI->replaceAllUsesWith(Replace); |
| CI->eraseFromParent(); |
| #else |
| abort(); |
| #endif |
| } else if (V == module->GetClassDelegateeFunction) { |
| Changed = true; |
| BasicBlock* NBB = II->getParent()->splitBasicBlock(II); |
| I->getParent()->getTerminator()->eraseFromParent(); |
| Value* Del = getDelegatee(module, Call.getArgument(0), CI); |
| Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, Del, |
| module->JavaObjectNullConstant, "", CI); |
| |
| BasicBlock* NoDelegatee = BasicBlock::Create("No delegatee", &F); |
| BasicBlock* DelegateeOK = BasicBlock::Create("Delegatee OK", &F); |
| BranchInst::Create(NoDelegatee, DelegateeOK, cmp, CI); |
| PHINode* phi = PHINode::Create(module->JavaObjectType, "", DelegateeOK); |
| phi->addIncoming(Del, CI->getParent()); |
| |
| Value* Res = CallInst::Create(module->RuntimeDelegateeFunction, |
| Call.getArgument(0), "", NoDelegatee); |
| BranchInst::Create(DelegateeOK, NoDelegatee); |
| phi->addIncoming(Res, NoDelegatee); |
| |
| CI->replaceAllUsesWith(phi); |
| CI->eraseFromParent(); |
| BranchInst::Create(NBB, DelegateeOK); |
| break; |
| |
| } else if (V == module->InitialisationCheckFunction) { |
| Changed = true; |
| |
| BasicBlock* NBB = 0; |
| if (CI->getParent()->getTerminator() != CI) { |
| NBB = II->getParent()->splitBasicBlock(II); |
| CI->getParent()->getTerminator()->eraseFromParent(); |
| } else { |
| InvokeInst* Invoke = dyn_cast<InvokeInst>(CI); |
| assert(Invoke && "Last instruction is not an invoke"); |
| NBB = Invoke->getNormalDest(); |
| } |
| |
| Value* Cl = Call.getArgument(0); |
| Value* TCM = getTCM(module, Call.getArgument(0), CI); |
| Value* GEP[2] = { module->constantZero, |
| module->OffsetStatusInTaskClassMirrorConstant }; |
| Value* StatusPtr = GetElementPtrInst::Create(TCM, GEP, GEP + 2, "", |
| CI); |
| |
| Value* Status = new LoadInst(StatusPtr, "", CI); |
| |
| Value* test = new ICmpInst(ICmpInst::ICMP_EQ, Status, |
| jnjvm::JnjvmModule::ClassReadyConstant, |
| "", CI); |
| |
| BasicBlock* trueCl = BasicBlock::Create("Initialized", &F); |
| BasicBlock* falseCl = BasicBlock::Create("Uninitialized", &F); |
| PHINode* node = llvm::PHINode::Create(JnjvmModule::JavaClassType, "", trueCl); |
| node->addIncoming(Cl, CI->getParent()); |
| BranchInst::Create(trueCl, falseCl, test, CI); |
| |
| |
| Value* res = 0; |
| if (InvokeInst* Invoke = dyn_cast<InvokeInst>(CI)) { |
| Value* Args[1] = { Cl }; |
| BasicBlock* UI = Invoke->getUnwindDest(); |
| res = InvokeInst::Create(module->InitialiseClassFunction, |
| trueCl, UI, Args, Args + 1, |
| "", falseCl); |
| |
| // For some reason, an LLVM pass may add PHI nodes to the |
| // exception destination. |
| BasicBlock::iterator Temp = UI->getInstList().begin(); |
| while (PHINode* PHI = dyn_cast<PHINode>(Temp)) { |
| Value* Val = PHI->getIncomingValueForBlock(CI->getParent()); |
| PHI->removeIncomingValue(CI->getParent(), false); |
| PHI->addIncoming(Val, falseCl); |
| Temp++; |
| } |
| |
| // And here we set the phi nodes of the normal dest of the Invoke |
| // instruction. The phi nodes have now the trueCl as basic block. |
| Temp = NBB->getInstList().begin(); |
| while (PHINode* PHI = dyn_cast<PHINode>(Temp)) { |
| Value* Val = PHI->getIncomingValueForBlock(CI->getParent()); |
| PHI->removeIncomingValue(CI->getParent(), false); |
| PHI->addIncoming(Val, trueCl); |
| Temp++; |
| } |
| } else { |
| res = CallInst::Create(module->InitialiseClassFunction, |
| Cl, "", falseCl); |
| BranchInst::Create(trueCl, falseCl); |
| } |
| |
| node->addIncoming(res, falseCl); |
| |
| |
| CI->replaceAllUsesWith(node); |
| CI->eraseFromParent(); |
| BranchInst::Create(NBB, trueCl); |
| break; |
| } else if (V == module->GetConstantPoolAtFunction) { |
| Function* resolver = dyn_cast<Function>(Call.getArgument(0)); |
| assert(resolver && "Wrong use of GetConstantPoolAt"); |
| const Type* returnType = resolver->getReturnType(); |
| Value* CTP = Call.getArgument(1); |
| Value* Index = Call.getArgument(3); |
| Changed = true; |
| BasicBlock* NBB = 0; |
| if (CI->getParent()->getTerminator() != CI) { |
| NBB = II->getParent()->splitBasicBlock(II); |
| CI->getParent()->getTerminator()->eraseFromParent(); |
| } else { |
| InvokeInst* Invoke = dyn_cast<InvokeInst>(CI); |
| assert(Invoke && "Last instruction is not an invoke"); |
| NBB = Invoke->getNormalDest(); |
| } |
| |
| #ifdef ISOLATE_SHARING |
| ConstantInt* Cons = dyn_cast<ConstantInt>(Index); |
| assert(CI && "Wrong use of GetConstantPoolAt"); |
| uint64 val = Cons->getZExtValue(); |
| Value* indexes = ConstantInt::get(Type::Int32Ty, val + 1); |
| #else |
| Value* indexes = Index; |
| #endif |
| Value* arg1 = GetElementPtrInst::Create(CTP, indexes, "", CI); |
| arg1 = new LoadInst(arg1, "", false, CI); |
| Value* test = new ICmpInst(ICmpInst::ICMP_EQ, arg1, |
| mvm::MvmModule::constantPtrNull, "", CI); |
| |
| BasicBlock* trueCl = BasicBlock::Create("Ctp OK", &F); |
| BasicBlock* falseCl = BasicBlock::Create("Ctp Not OK", &F); |
| PHINode* node = llvm::PHINode::Create(returnType, "", trueCl); |
| node->addIncoming(arg1, CI->getParent()); |
| BranchInst::Create(falseCl, trueCl, test, CI); |
| |
| std::vector<Value*> Args; |
| unsigned ArgSize = Call.arg_size(), i = 1; |
| while (++i < ArgSize) { |
| Args.push_back(Call.getArgument(i)); |
| } |
| |
| Value* res = 0; |
| if (InvokeInst* Invoke = dyn_cast<InvokeInst>(CI)) { |
| BasicBlock* UI = Invoke->getUnwindDest(); |
| res = InvokeInst::Create(resolver, trueCl, UI, Args.begin(), |
| Args.end(), "", falseCl); |
| |
| // For some reason, an LLVM pass may add PHI nodes to the |
| // exception destination. |
| BasicBlock::iterator Temp = UI->getInstList().begin(); |
| while (PHINode* PHI = dyn_cast<PHINode>(Temp)) { |
| Value* Val = PHI->getIncomingValueForBlock(CI->getParent()); |
| PHI->removeIncomingValue(CI->getParent(), false); |
| PHI->addIncoming(Val, falseCl); |
| Temp++; |
| } |
| |
| // And here we set the phi nodes of the normal dest of the Invoke |
| // instruction. The phi nodes have now the trueCl as basic block. |
| Temp = NBB->getInstList().begin(); |
| while (PHINode* PHI = dyn_cast<PHINode>(Temp)) { |
| Value* Val = PHI->getIncomingValueForBlock(CI->getParent()); |
| PHI->removeIncomingValue(CI->getParent(), false); |
| PHI->addIncoming(Val, trueCl); |
| Temp++; |
| } |
| |
| } else { |
| res = CallInst::Create(resolver, Args.begin(), Args.end(), "", |
| falseCl); |
| BranchInst::Create(trueCl, falseCl); |
| } |
| |
| node->addIncoming(res, falseCl); |
| |
| |
| CI->replaceAllUsesWith(node); |
| CI->eraseFromParent(); |
| BranchInst::Create(NBB, trueCl); |
| break; |
| } else if (V == module->GetArrayClassFunction) { |
| const llvm::Type* Ty = |
| PointerType::getUnqual(module->JavaCommonClassType); |
| Constant* nullValue = Constant::getNullValue(Ty); |
| // Check if we have already proceed this call. |
| if (Call.getArgument(1) == nullValue) { |
| Changed = true; |
| ConstantExpr* CE = getClass(module, Call); |
| if (CE) { |
| ConstantInt* C = (ConstantInt*)CE->getOperand(0); |
| Class* cl = (Class*)C->getZExtValue(); |
| if (cl->isResolved()) { |
| JnjvmClassLoader* JCL = cl->classLoader; |
| const UTF8* arrayName = JCL->constructArrayName(1, cl->name); |
| |
| UserCommonClass* dcl = JCL->constructArray(arrayName); |
| Value* valCl = module->getNativeClass(dcl, CI); |
| CI->replaceAllUsesWith(valCl); |
| CI->eraseFromParent(); |
| continue; |
| } |
| } |
| |
| BasicBlock* NBB = II->getParent()->splitBasicBlock(II); |
| I->getParent()->getTerminator()->eraseFromParent(); |
| |
| Constant* init = |
| Constant::getNullValue(module->JavaCommonClassType); |
| GlobalVariable* GV = |
| new GlobalVariable(module->JavaCommonClassType, false, |
| GlobalValue::ExternalLinkage, |
| init, "", module); |
| |
| Value* LoadedGV = new LoadInst(GV, "", CI); |
| Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, LoadedGV, init, |
| "", CI); |
| |
| BasicBlock* OKBlock = BasicBlock::Create("", &F); |
| BasicBlock* NotOKBlock = BasicBlock::Create("", &F); |
| PHINode* node = PHINode::Create(module->JavaCommonClassType, "", |
| OKBlock); |
| node->addIncoming(LoadedGV, CI->getParent()); |
| |
| BranchInst::Create(NotOKBlock, OKBlock, cmp, CI); |
| |
| Value* args[2] = { Call.getArgument(0), GV }; |
| Value* res = CallInst::Create(module->GetArrayClassFunction, args, |
| args + 2, "", NotOKBlock); |
| BranchInst::Create(OKBlock, NotOKBlock); |
| node->addIncoming(res, NotOKBlock); |
| |
| CI->replaceAllUsesWith(node); |
| CI->eraseFromParent(); |
| BranchInst::Create(NBB, OKBlock); |
| break; |
| } |
| } |
| |
| #ifdef ISOLATE_SHARING |
| else if (V == module->GetCtpClassFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| Value* indexes[2] = { module->constantZero, |
| module->OffsetCtpInClassConstant }; |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes, |
| indexes + 2, "", CI); |
| Value* VT = new LoadInst(VTPtr, "", CI); |
| CI->replaceAllUsesWith(VT); |
| CI->eraseFromParent(); |
| } else if (V == module->GetCtpCacheNodeFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| Value* indexes[2] = { module->constantZero, module->constantFour }; |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes, |
| indexes + 2, "", CI); |
| Value* VT = new LoadInst(VTPtr, "", CI); |
| CI->replaceAllUsesWith(VT); |
| CI->eraseFromParent(); |
| } else if (V == module->GetJnjvmArrayClassFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| Value* index = Call.getArgument(1); |
| Value* indexes[3] = { module->constantZero, module->constantTwo, |
| index }; |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes, indexes + 3, |
| "", CI); |
| Value* VT = new LoadInst(VTPtr, "", CI); |
| CI->replaceAllUsesWith(VT); |
| CI->eraseFromParent(); |
| } else if (V == module->GetJnjvmExceptionClassFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| Value* indexes[2] = { module->constantZero, module->constantOne }; |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes, indexes + 2, |
| "", CI); |
| Value* VT = new LoadInst(VTPtr, "", CI); |
| CI->replaceAllUsesWith(VT); |
| CI->eraseFromParent(); |
| } |
| #endif |
| |
| } |
| } |
| } |
| return Changed; |
| } |
| |
| |
| FunctionPass* createLowerConstantCallsPass() { |
| return new LowerConstantCalls(); |
| } |
| |
| class VISIBILITY_HIDDEN LowerForcedCalls : public FunctionPass { |
| public: |
| static char ID; |
| LowerForcedCalls() : FunctionPass((intptr_t)&ID) { } |
| |
| virtual bool runOnFunction(Function &F); |
| private: |
| }; |
| char LowerForcedCalls::ID = 0; |
| static RegisterPass<LowerForcedCalls> Y("LowerForcedCalls", |
| "Lower Forced calls"); |
| |
| bool LowerForcedCalls::runOnFunction(Function& F) { |
| JnjvmModule* module = (JnjvmModule*)F.getParent(); |
| bool Changed = false; |
| for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) { |
| BasicBlock *Cur = BI; |
| for (BasicBlock::iterator II = Cur->begin(), IE = Cur->end(); II != IE;) { |
| Instruction *I = II; |
| II++; |
| if (CallInst *CI = dyn_cast<CallInst>(I)) { |
| Value* V = CI->getOperand(0); |
| if (V == module->ForceInitialisationCheckFunction) { |
| Changed = true; |
| CI->eraseFromParent(); |
| } |
| } |
| } |
| } |
| return Changed; |
| } |
| |
| FunctionPass* createLowerForcedCallsPass() { |
| return new LowerForcedCalls(); |
| } |
| |
| } |