blob: ca7ad918e73cdd9b2323cd38fdfac0610cf37f40 [file] [log] [blame]
//===----- 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();
}
}