|
|
|
|
@ -14,61 +14,60 @@ using std::string;
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
class ClassIMPCachePass : public FunctionPass
|
|
|
|
|
class ClassIMPCachePass : public ModulePass
|
|
|
|
|
{
|
|
|
|
|
GNUstep::IMPCacher *cacher;
|
|
|
|
|
Module *M;
|
|
|
|
|
const IntegerType *IntTy;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
static char ID;
|
|
|
|
|
ClassIMPCachePass() : FunctionPass((intptr_t)&ID) {}
|
|
|
|
|
~ClassIMPCachePass() { delete cacher; }
|
|
|
|
|
ClassIMPCachePass() : ModulePass((intptr_t)&ID) {}
|
|
|
|
|
|
|
|
|
|
virtual bool doInitialization(Module &Mod) {
|
|
|
|
|
M = &Mod;
|
|
|
|
|
cacher = new GNUstep::IMPCacher(Mod.getContext(), this);
|
|
|
|
|
virtual bool runOnModule(Module &M) {
|
|
|
|
|
GNUstep::IMPCacher cacher = GNUstep::IMPCacher(M.getContext(), this);
|
|
|
|
|
// FIXME: ILP64
|
|
|
|
|
IntTy = Type::getInt32Ty(Mod.getContext());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual bool runOnFunction(Function &F) {
|
|
|
|
|
IntTy = Type::getInt32Ty(M.getContext());
|
|
|
|
|
bool modified = false;
|
|
|
|
|
SmallVector<CallInst*, 16> Lookups;
|
|
|
|
|
BasicBlock *entry = &F.getEntryBlock();
|
|
|
|
|
|
|
|
|
|
for (Function::iterator i=F.begin(), end=F.end() ;
|
|
|
|
|
i != end ; ++i) {
|
|
|
|
|
for (BasicBlock::iterator b=i->begin(), last=i->end() ;
|
|
|
|
|
b != last ; ++b) {
|
|
|
|
|
if (CallInst *call = dyn_cast<CallInst>(b)) {
|
|
|
|
|
Value *callee = call->getCalledValue()->stripPointerCasts();
|
|
|
|
|
if (Function *func = dyn_cast<Function>(callee)) {
|
|
|
|
|
if (func->getName() == "objc_msg_lookup_sender") {
|
|
|
|
|
// TODO: Move this to a helper
|
|
|
|
|
Value *receiverPtr = call->getOperand(1);
|
|
|
|
|
Value *receiver = 0;
|
|
|
|
|
// Find where the receiver comes from
|
|
|
|
|
for (BasicBlock::iterator start=i->begin(),s=b ; s!=start ; s--) {
|
|
|
|
|
if (StoreInst *store = dyn_cast<StoreInst>(s)) {
|
|
|
|
|
if (store->getOperand(1) == receiverPtr) {
|
|
|
|
|
receiver = store->getOperand(0);
|
|
|
|
|
break;
|
|
|
|
|
for (Module::iterator F=M.begin(), fend=M.end() ;
|
|
|
|
|
F != fend ; ++F) {
|
|
|
|
|
|
|
|
|
|
if (F->isDeclaration()) { continue; }
|
|
|
|
|
|
|
|
|
|
SmallVector<CallInst*, 16> Lookups;
|
|
|
|
|
BasicBlock *entry = &F->getEntryBlock();
|
|
|
|
|
|
|
|
|
|
for (Function::iterator i=F->begin(), end=F->end() ;
|
|
|
|
|
i != end ; ++i) {
|
|
|
|
|
for (BasicBlock::iterator b=i->begin(), last=i->end() ;
|
|
|
|
|
b != last ; ++b) {
|
|
|
|
|
if (CallInst *call = dyn_cast<CallInst>(b)) {
|
|
|
|
|
Value *callee = call->getCalledValue()->stripPointerCasts();
|
|
|
|
|
if (Function *func = dyn_cast<Function>(callee)) {
|
|
|
|
|
if (func->getName() == "objc_msg_lookup_sender") {
|
|
|
|
|
// TODO: Move this to a helper
|
|
|
|
|
Value *receiverPtr = call->getOperand(1);
|
|
|
|
|
Value *receiver = 0;
|
|
|
|
|
// Find where the receiver comes from
|
|
|
|
|
for (BasicBlock::iterator start=i->begin(),s=b ; s!=start ; s--) {
|
|
|
|
|
if (StoreInst *store = dyn_cast<StoreInst>(s)) {
|
|
|
|
|
if (store->getOperand(1) == receiverPtr) {
|
|
|
|
|
receiver = store->getOperand(0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (0 == receiver) { continue; }
|
|
|
|
|
if (CallInst *classLookup = dyn_cast<CallInst>(receiver)) {
|
|
|
|
|
Value *lookupVal = classLookup->getCalledValue()->stripPointerCasts();
|
|
|
|
|
if (Function *lookupFunc = dyn_cast<Function>(lookupVal)) {
|
|
|
|
|
if (lookupFunc->getName() == "objc_lookup_class") {
|
|
|
|
|
GlobalVariable *classNameVar = cast<GlobalVariable>(
|
|
|
|
|
classLookup->getOperand(1)->stripPointerCasts());
|
|
|
|
|
string className = cast<ConstantArray>(
|
|
|
|
|
classNameVar->getInitializer() )->getAsString();
|
|
|
|
|
modified = true;
|
|
|
|
|
Lookups.push_back(call);
|
|
|
|
|
if (0 == receiver) { continue; }
|
|
|
|
|
if (CallInst *classLookup = dyn_cast<CallInst>(receiver)) {
|
|
|
|
|
Value *lookupVal = classLookup->getCalledValue()->stripPointerCasts();
|
|
|
|
|
if (Function *lookupFunc = dyn_cast<Function>(lookupVal)) {
|
|
|
|
|
if (lookupFunc->getName() == "objc_lookup_class") {
|
|
|
|
|
GlobalVariable *classNameVar = cast<GlobalVariable>(
|
|
|
|
|
classLookup->getOperand(1)->stripPointerCasts());
|
|
|
|
|
string className = cast<ConstantArray>(
|
|
|
|
|
classNameVar->getInitializer() )->getAsString();
|
|
|
|
|
modified = true;
|
|
|
|
|
Lookups.push_back(call);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -76,19 +75,19 @@ namespace
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
IRBuilder<> B = IRBuilder<>(entry);
|
|
|
|
|
for (SmallVectorImpl<CallInst*>::iterator i=Lookups.begin(),
|
|
|
|
|
e=Lookups.end() ; e!=i ; i++) {
|
|
|
|
|
const Type *SlotPtrTy = (*i)->getType();
|
|
|
|
|
IRBuilder<> B = IRBuilder<>(entry);
|
|
|
|
|
for (SmallVectorImpl<CallInst*>::iterator i=Lookups.begin(),
|
|
|
|
|
e=Lookups.end() ; e!=i ; i++) {
|
|
|
|
|
const Type *SlotPtrTy = (*i)->getType();
|
|
|
|
|
|
|
|
|
|
Value *slot = new GlobalVariable(*M, SlotPtrTy, false,
|
|
|
|
|
GlobalValue::PrivateLinkage, Constant::getNullValue(SlotPtrTy),
|
|
|
|
|
"slot");
|
|
|
|
|
Value *version = new GlobalVariable(*M, IntTy, false,
|
|
|
|
|
GlobalValue::PrivateLinkage, Constant::getNullValue(IntTy),
|
|
|
|
|
"version");
|
|
|
|
|
cacher->CacheLookup(*i, slot, version);
|
|
|
|
|
Value *slot = new GlobalVariable(M, SlotPtrTy, false,
|
|
|
|
|
GlobalValue::PrivateLinkage, Constant::getNullValue(SlotPtrTy),
|
|
|
|
|
"slot");
|
|
|
|
|
Value *version = new GlobalVariable(M, IntTy, false,
|
|
|
|
|
GlobalValue::PrivateLinkage, Constant::getNullValue(IntTy),
|
|
|
|
|
"version");
|
|
|
|
|
cacher.CacheLookup(*i, slot, version);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return modified;
|
|
|
|
|
}
|
|
|
|
|
@ -99,7 +98,7 @@ namespace
|
|
|
|
|
"Cache IMPs for class messages");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FunctionPass *createClassIMPCachePass(void)
|
|
|
|
|
ModulePass *createClassIMPCachePass(void)
|
|
|
|
|
{
|
|
|
|
|
return new ClassIMPCachePass();
|
|
|
|
|
}
|
|
|
|
|
|