bool handleFlavor(LoadInst *li, ConstantExpr *gepce) { if (VERBOSITY("opt") >= 1) { errs() << "\nFound this load of a flavor attr:\n" << *li << '\n'; } GetElementPtrInst *gep = cast<GetElementPtrInst>(gepce->getAsInstruction()); APInt ap_offset(64, 0, true); bool success = gep->accumulateConstantOffset(*g.tm->getDataLayout(), ap_offset); delete gep; assert(success); int64_t offset = ap_offset.getSExtValue(); if (offset == FLAVOR_KINDID_OFFSET) { ObjectFlavor* flavor = getFlavorFromGV(cast<GlobalVariable>(gepce->getOperand(0))); replaceUsesWithConstant(li, flavor->kind_id); return true; } else { ASSERT(0, "%ld", offset); return false; } assert(0); return false; }
bool detail::PtrUseVisitorBase::adjustOffsetForGEP(GetElementPtrInst &GEPI) { if (!IsOffsetKnown) return false; return GEPI.accumulateConstantOffset(DL, Offset); }
bool handleCls(LoadInst *li, GlobalVariable *gv) { bool changed = true; if (VERBOSITY("opt") >= 1) { errs() << "\nFound load of class-typed global variable:\n" << *li << '\n'; } BoxedClass *cls = getClassFromGV(gv); if (!cls->is_constant) { assert(0 && "what globally-resolved classes are not constant??"); if (VERBOSITY("opt") >= 1) { errs() << gv->getName() << " is not constant; moving on\n"; } return false; } std::vector<Instruction*> to_remove; for (User* user : li->users()) { if (CallInst *call = dyn_cast<CallInst>(user)) { if (call->getCalledFunction()->getName() == "_maybeDecrefCls") { errs() << "Found decrefcls call: " << *call << '\n'; if (!isUserDefined(cls)) { // Don't delete right away; I think that invalidates the iterator // we're currently iterating over to_remove.push_back(call); } } continue; } GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>(user); if (!gep) { //errs() << "Not a gep: " << *user << '\n'; continue; } APInt ap_offset(64, 0, true); bool success = gep->accumulateConstantOffset(*g.tm->getDataLayout(), ap_offset); assert(success); int64_t offset = ap_offset.getSExtValue(); errs() << "Found a gep at offset " << offset << ": " << *gep << '\n'; for (User* gep_user : gep->users()) { LoadInst *gep_load = dyn_cast<LoadInst>(gep_user); if (!gep_load) { //errs() << "Not a load: " << *gep_user << '\n'; continue; } errs() << "Found a load: " << *gep_load << '\n'; if (offset == CLS_DTOR_OFFSET) { errs() << "Dtor; replacing with " << cls->dtor << "\n"; replaceUsesWithConstant(gep_load, (uintptr_t)cls->dtor); changed = true; } else if (offset == CLS_HASATTRS_OFFSET) { errs() << "Hasattrs; replacing with " << cls->hasattrs << "\n"; replaceUsesWithConstant(gep_load, cls->hasattrs); changed = true; } } } for (int i = 0; i < to_remove.size(); i++) { to_remove[i]->eraseFromParent(); changed = true; } if (VERBOSITY()) { llvm::errs() << "Constant-folding this load: " << *li << '\n'; } li->replaceAllUsesWith(embedConstantPtr(cls, g.llvm_class_type_ptr)); changed = true; return changed; }
bool handleCls(LoadInst* li, GlobalVariable* gv) { bool changed = true; if (VERBOSITY("opt") >= 1) { errs() << "\nFound load of class-typed global variable:\n" << *li << '\n'; } BoxedClass* cls = getClassFromGV(gv); if (!cls->is_constant) { assert(0 && "what globally-resolved classes are not constant??"); if (VERBOSITY("opt") >= 1) { errs() << gv->getName() << " is not constant; moving on\n"; } return false; } std::vector<Instruction*> to_remove; for (User* user : li->users()) { if (CallInst* call = dyn_cast<CallInst>(user)) { continue; } GetElementPtrInst* gep = dyn_cast<GetElementPtrInst>(user); if (!gep) { // errs() << "Not a gep: " << *user << '\n'; continue; } APInt ap_offset(64, 0, true); #if LLVMREV < 214781 bool success = gep->accumulateConstantOffset(*g.tm->getDataLayout(), ap_offset); #elif LLVMREV < 227113 bool success = gep->accumulateConstantOffset(*g.tm->getSubtargetImpl()->getDataLayout(), ap_offset); #else bool success = gep->accumulateConstantOffset(*g.tm->getDataLayout(), ap_offset); #endif assert(success); int64_t offset = ap_offset.getSExtValue(); if (VERBOSITY("opt") >= 1) errs() << "Found a gep at offset " << offset << ": " << *gep << '\n'; for (User* gep_user : gep->users()) { LoadInst* gep_load = dyn_cast<LoadInst>(gep_user); if (!gep_load) { // errs() << "Not a load: " << *gep_user << '\n'; continue; } if (VERBOSITY("opt") >= 1) errs() << "Found a load: " << *gep_load << '\n'; if (offset == offsetof(BoxedClass, attrs_offset)) { if (VERBOSITY("opt") >= 1) errs() << "attrs_offset; replacing with " << cls->attrs_offset << "\n"; replaceUsesWithConstant(gep_load, cls->attrs_offset); changed = true; } else if (offset == offsetof(BoxedClass, tp_basicsize)) { if (VERBOSITY("opt") >= 1) errs() << "tp_basicsize; replacing with " << cls->tp_basicsize << "\n"; replaceUsesWithConstant(gep_load, cls->tp_basicsize); changed = true; } } } for (int i = 0; i < to_remove.size(); i++) { to_remove[i]->eraseFromParent(); changed = true; } if (VERBOSITY()) { llvm::errs() << "Constant-folding this load: " << *li << '\n'; } li->replaceAllUsesWith(embedConstantPtr(cls, g.llvm_class_type_ptr)); changed = true; return changed; }