// // Copyright (c) rev.ng Srls. See LICENSE.md for details. // #include #include #include #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" #include "llvm/IR/Verifier.h" #include "llvm/PassSupport.h" #include "llvm/Support/Casting.h" #include "revng/Support/Assert.h" #include "revng/Support/Debug.h" #include "revng-c/PromoteStackPointer/PromoteStackPointerPass.h" static Logger<> Log("promote-stack-pointer"); bool PromoteStackPointerPass::runOnFunction(llvm::Function &F) { // Get the global variable representing the stack pointer register. using GCBIPass = GeneratedCodeBasicInfoWrapperPass; llvm::GlobalVariable *GlobalSP = getAnalysis().getGCBI().spReg(); std::vector SPUsers; for (llvm::User *U : GlobalSP->users()) { if (auto *I = llvm::dyn_cast(U)) { llvm::Function *UserFun = I->getFunction(); revng_log(Log, "Found use in Function: " << UserFun->getName()); if (UserFun != &F) continue; SPUsers.emplace_back(I); } else if (auto *CE = llvm::dyn_cast(U)) { revng_log(Log, "Found ConstantExpr use"); if (not CE->getNumUses()) continue; llvm::SmallVector, 8> Replacements; for (llvm::User *CEUser : CE->users()) { auto *CEInstrUser = llvm::cast(CEUser); llvm::Function *UserFun = CEInstrUser->getFunction(); if (UserFun != &F) continue; auto *CastInstruction = CE->getAsInstruction(); CastInstruction->insertBefore(CEInstrUser); SPUsers.emplace_back(CastInstruction); Replacements.push_back({ CEInstrUser, CastInstruction }); } for (const auto &[User, CEUseReplacement] : Replacements) User->replaceUsesOfWith(CE, CEUseReplacement); } else { revng_unreachable(); } } if (SPUsers.empty()) return false; // Create function for initializing local stack pointer. llvm::Module *M = F.getParent(); llvm::LLVMContext &Ctx = F.getContext(); llvm::Type *SPType = GlobalSP->getType()->getPointerElementType(); uint64_t PointerBitWidth = SPType->getPrimitiveSizeInBits().getFixedSize(); llvm::Type *IntTy = llvm::Type::getIntNTy(Ctx, PointerBitWidth); auto InitFunction = M->getOrInsertFunction("revng_init_local_sp", SPType, IntTy); llvm::Function *InitLocalSP = cast(InitFunction.getCallee()); // Create an alloca to represent the local value of the stack pointer. // This should be inserted at the beginning of the entry block. llvm::BasicBlock &EntryBlock = F.getEntryBlock(); llvm::IRBuilder<> Builder(Ctx); Builder.SetInsertPoint(&EntryBlock, EntryBlock.begin()); llvm::AllocaInst *LocalSP = Builder.CreateAlloca(SPType, nullptr, "local_sp"); // Call InitLocalSP, to initialize the value of the local stack pointer. // The argument to the call is always zero. This argument will be adjusted by // AdjustStackPointerPass to represent how much the stack pointer is adjusted. llvm::APInt APZero = llvm::APInt::getNullValue(IntTy->getIntegerBitWidth()); llvm::Constant *Zero = llvm::Constant::getIntegerValue(IntTy, APZero); auto *InitSPVal = Builder.CreateCall(InitLocalSP, Zero); Builder.CreateStore(InitSPVal, LocalSP); // Actually perform the replacement. for (llvm::Instruction *I : SPUsers) { // Switch all the uses of the GlobalSP in I to uses of the LocalSP. I->replaceUsesOfWith(GlobalSP, LocalSP); } return true; } char PromoteStackPointerPass::ID = 0; using llvm::RegisterPass; using Pass = PromoteStackPointerPass; static RegisterPass RegisterPromoteStackPtr("promote-stack-pointer", "Promote Stack Pointer Pass");