| //===----- 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; |
| using namespace jnjvm; |
| |
| namespace mvm { |
| |
| 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) { |
| std::vector<Value*> GEP; |
| GEP.push_back(module->constantZero); |
| GEP.push_back(module->OffsetTaskClassMirrorInClassConstant); |
| Value* TCMArray = GetElementPtrInst::Create(Arg, GEP.begin(), GEP.end(), |
| "", 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); |
| |
| GEP.clear(); |
| GEP.push_back(module->constantThree); |
| Value* IsolateID = GetElementPtrInst::Create(threadId, GEP.begin(), GEP.end(), |
| "", CI); |
| IsolateID = new LoadInst(IsolateID, "", CI); |
| |
| GEP.clear(); |
| GEP.push_back(module->constantZero); |
| GEP.push_back(IsolateID); |
| Value* TCM = GetElementPtrInst::Create(TCMArray, GEP.begin(), GEP.end(), "", |
| CI); |
| return TCM; |
| } |
| #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); |
| std::vector<Value*> args; //size= 2 |
| args.push_back(mvm::MvmModule::constantZero); |
| args.push_back(module->JavaArraySizeOffsetConstant); |
| Value* ptr = GetElementPtrInst::Create(array, args.begin(), args.end(), |
| "", 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 |
| std::vector<Value*> indexes; //[3]; |
| indexes.push_back(mvm::MvmModule::constantZero); |
| indexes.push_back(mvm::MvmModule::constantZero); |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes.begin(), |
| indexes.end(), "", 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 |
| std::vector<Value*> args2; |
| args2.push_back(mvm::MvmModule::constantZero); |
| args2.push_back(module->JavaObjectClassOffsetConstant); |
| Value* classPtr = GetElementPtrInst::Create(val, args2.begin(), |
| args2.end(), "", |
| 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); |
| VT = new LoadInst(VT, "", CI); |
| CI->replaceAllUsesWith(VT); |
| CI->eraseFromParent(); |
| continue; |
| } |
| } |
| |
| Value* val = Call.getArgument(0); |
| std::vector<Value*> indexes; |
| indexes.push_back(mvm::MvmModule::constantZero); |
| indexes.push_back(module->OffsetVTInClassConstant); |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes.begin(), |
| indexes.end(), "", 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); |
| std::vector<Value*> indexes; |
| indexes.push_back(mvm::MvmModule::constantZero); |
| indexes.push_back(module->OffsetObjectSizeInClassConstant); |
| Value* SizePtr = GetElementPtrInst::Create(val, indexes.begin(), |
| indexes.end(), "", CI); |
| Value* Size = new LoadInst(SizePtr, "", CI); |
| CI->replaceAllUsesWith(Size); |
| CI->eraseFromParent(); |
| } else if (V == module->GetDepthFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| std::vector<Value*> indexes; |
| indexes.push_back(mvm::MvmModule::constantZero); |
| indexes.push_back(module->OffsetDepthInClassConstant); |
| Value* DepthPtr = GetElementPtrInst::Create(val, indexes.begin(), |
| indexes.end(), "", CI); |
| Value* Depth = new LoadInst(DepthPtr, "", CI); |
| CI->replaceAllUsesWith(Depth); |
| CI->eraseFromParent(); |
| } else if (V == module->GetDisplayFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| std::vector<Value*> indexes; |
| indexes.push_back(mvm::MvmModule::constantZero); |
| indexes.push_back(module->OffsetDisplayInClassConstant); |
| Value* DisplayPtr = GetElementPtrInst::Create(val, indexes.begin(), |
| indexes.end(), "", 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)) { |
| std::vector<Value*> args; |
| args.push_back(objCl); |
| args.push_back(CE); |
| Value* res = CallInst::Create(module->ImplementsFunction, |
| args.begin(), args.end(), "", |
| 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->status < classRead) { |
| std::vector<Value*> args; |
| args.push_back(objCl); |
| args.push_back(CE); |
| cmp = CallInst::Create(module->IsAssignableFromFunction, |
| args.begin(), args.end(), "", notEquals); |
| node->addIncoming(cmp, notEquals); |
| BranchInst::Create(ifTrue, notEquals); |
| } else if (cl->isArray()) { |
| std::vector<Value*> args; |
| args.push_back(objCl); |
| args.push_back(CE); |
| Value* res = |
| CallInst::Create(module->InstantiationOfArrayFunction, |
| args.begin(), args.end(), "", notEquals); |
| node->addIncoming(res, notEquals); |
| BranchInst::Create(ifTrue, notEquals); |
| } else { |
| Value* depthCl; |
| if (cl->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); |
| |
| std::vector<Value*> args; |
| args.push_back(inDisplay); |
| args.push_back(depthCl); |
| Value* clInDisplay = |
| CallInst::Create(module->GetClassInDisplayFunction, |
| args.begin(), args.end(), "", 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); |
| Replace = new LoadInst(Replace, "", CI); |
| CI->replaceAllUsesWith(Replace); |
| CI->eraseFromParent(); |
| |
| #elif defined(ISOLATE) |
| Value* TCM = getTCM(module, Call.getArgument(0), CI); |
| std::vector<Value*> GEP; |
| GEP.push_back(module->constantZero); |
| GEP.push_back(module->OffsetStaticInstanceInTaskClassMirrorConstant); |
| Value* Replace = GetElementPtrInst::Create(TCM, GEP.begin(), |
| GEP.end(), "", CI); |
| Replace = new LoadInst(Replace, "", CI); |
| CI->replaceAllUsesWith(Replace); |
| CI->eraseFromParent(); |
| #else |
| abort(); |
| #endif |
| |
| } 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); |
| #if !defined(ISOLATE) |
| std::vector<Value*> indexes; |
| indexes.push_back(mvm::MvmModule::constantZero); |
| indexes.push_back(module->OffsetStatusInClassConstant); |
| Value* StatusPtr = GetElementPtrInst::Create(Cl, indexes.begin(), |
| indexes.end(), "", CI); |
| |
| #else |
| Value* TCM = getTCM(module, Call.getArgument(0), CI); |
| std::vector<Value*> GEP; |
| GEP.push_back(module->constantZero); |
| GEP.push_back(module->OffsetStatusInTaskClassMirrorConstant); |
| Value* StatusPtr = GetElementPtrInst::Create(TCM, GEP.begin(), |
| GEP.end(), "", CI); |
| #endif |
| |
| 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); |
| |
| std::vector<Value*> Args; |
| Args.push_back(Cl); |
| |
| Value* res = 0; |
| if (InvokeInst* Invoke = dyn_cast<InvokeInst>(CI)) { |
| BasicBlock* UI = Invoke->getUnwindDest(); |
| res = InvokeInst::Create(module->InitialiseClassFunction, |
| 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(module->InitialiseClassFunction, |
| 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->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(); |
| } |
| |
| std::vector<Value*> indexes; //[3]; |
| #ifdef ISOLATE_SHARING |
| ConstantInt* Cons = dyn_cast<ConstantInt>(Index); |
| assert(CI && "Wrong use of GetConstantPoolAt"); |
| uint64 val = Cons->getZExtValue(); |
| indexes.push_back(ConstantInt::get(Type::Int32Ty, val + 1)); |
| #else |
| indexes.push_back(Index); |
| #endif |
| Value* arg1 = GetElementPtrInst::Create(CTP, indexes.begin(), |
| indexes.end(), "", 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->JavaClassType); |
| 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); |
| valCl = new LoadInst(valCl, "", CI); |
| CI->replaceAllUsesWith(valCl); |
| CI->eraseFromParent(); |
| continue; |
| } |
| } |
| |
| BasicBlock* NBB = II->getParent()->splitBasicBlock(II); |
| I->getParent()->getTerminator()->eraseFromParent(); |
| |
| Constant* init = Constant::getNullValue(module->JavaClassType); |
| GlobalVariable* GV = |
| new GlobalVariable(module->JavaClassType, 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->JavaClassType, "", 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); |
| std::vector<Value*> indexes; |
| indexes.push_back(mvm::MvmModule::constantZero); |
| indexes.push_back(module->OffsetCtpInClassConstant); |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes.begin(), |
| indexes.end(), "", CI); |
| Value* VT = new LoadInst(VTPtr, "", CI); |
| CI->replaceAllUsesWith(VT); |
| CI->eraseFromParent(); |
| } else if (V == module->GetCtpCacheNodeFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| std::vector<Value*> indexes; |
| indexes.push_back(mvm::MvmModule::constantZero); |
| indexes.push_back(mvm::MvmModule::constantFour); |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes.begin(), |
| indexes.end(), "", 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); |
| std::vector<Value*> indexes; |
| indexes.push_back(mvm::MvmModule::constantZero); |
| indexes.push_back(mvm::MvmModule::constantTwo); |
| indexes.push_back(index); |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes.begin(), |
| indexes.end(), "", CI); |
| Value* VT = new LoadInst(VTPtr, "", CI); |
| CI->replaceAllUsesWith(VT); |
| CI->eraseFromParent(); |
| } else if (V == module->GetJnjvmExceptionClassFunction) { |
| Changed = true; |
| Value* val = Call.getArgument(0); |
| std::vector<Value*> indexes; |
| indexes.push_back(mvm::MvmModule::constantZero); |
| indexes.push_back(mvm::MvmModule::constantOne); |
| Value* VTPtr = GetElementPtrInst::Create(val, indexes.begin(), |
| indexes.end(), "", 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(); |
| } |
| |
| } |