diff --git a/anvill/src/Lifters/FunctionLifter.cpp b/anvill/src/Lifters/FunctionLifter.cpp index 0f3c83a1b..58ee97a54 100644 --- a/anvill/src/Lifters/FunctionLifter.cpp +++ b/anvill/src/Lifters/FunctionLifter.cpp @@ -32,14 +32,20 @@ #include #include #include -#include #include #include #include +#include #include #include +#include +#include +#include +#include +#include #include #include +#include #include #include #include @@ -1713,18 +1719,19 @@ void FunctionLifter::RecursivelyInlineLiftedFunctionIntoNativeFunction(void) { } // Initialize cleanup optimizations - llvm::legacy::FunctionPassManager fpm(semantics_module.get()); - fpm.add(llvm::createCFGSimplificationPass()); - fpm.add(llvm::createPromoteMemoryToRegisterPass()); - fpm.add(llvm::createReassociatePass()); - fpm.add(llvm::createDeadStoreEliminationPass()); - fpm.add(llvm::createDeadCodeEliminationPass()); - fpm.add(llvm::createSROAPass()); - fpm.add(llvm::createDeadCodeEliminationPass()); - fpm.add(llvm::createInstructionCombiningPass()); - fpm.doInitialization(); - fpm.run(*native_func); - fpm.doFinalization(); + llvm::PassBuilder pass_builder; + llvm::FunctionPassManager fpm; + llvm::FunctionAnalysisManager fam; + pass_builder.registerFunctionAnalyses(fam); + fpm.addPass(llvm::SimplifyCFGPass()); + fpm.addPass(llvm::PromotePass()); + fpm.addPass(llvm::ReassociatePass()); + fpm.addPass(llvm::DSEPass()); + fpm.addPass(llvm::DCEPass()); + fpm.addPass(llvm::SROA()); + fpm.addPass(llvm::DCEPass()); + fpm.addPass(llvm::InstCombinePass()); + fpm.run(*native_func, fam); ClearVariableNames(native_func); } diff --git a/anvill/src/Optimize.cpp b/anvill/src/Optimize.cpp index d86e35391..76d6da617 100644 --- a/anvill/src/Optimize.cpp +++ b/anvill/src/Optimize.cpp @@ -31,11 +31,24 @@ #include #include #include -#include #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +// #include #include // clang-format on @@ -84,63 +97,76 @@ void OptimizeModule(const EntityLifter &lifter_context, memory_escape->eraseFromParent(); } - llvm::legacy::PassManager mpm; - mpm.add(llvm::createFunctionInliningPass(250)); - mpm.add(llvm::createGlobalOptimizerPass()); - mpm.add(llvm::createGlobalDCEPass()); - mpm.add(llvm::createStripDeadDebugInfoPass()); - mpm.run(module); - - llvm::legacy::FunctionPassManager fpm(&module); - fpm.add(llvm::createDeadCodeEliminationPass()); - fpm.add(llvm::createSinkingPass()); - fpm.add(llvm::createNewGVNPass()); - fpm.add(llvm::createSCCPPass()); - fpm.add(llvm::createDeadStoreEliminationPass()); - fpm.add(llvm::createSROAPass()); - fpm.add(llvm::createEarlyCSEPass(true)); - fpm.add(llvm::createBitTrackingDCEPass()); - fpm.add(llvm::createCFGSimplificationPass()); - fpm.add(llvm::createSinkingPass()); - fpm.add(llvm::createCFGSimplificationPass()); - fpm.add(llvm::createInstructionCombiningPass()); + llvm::PassBuilder pass_builder; + llvm::LoopAnalysisManager lam; + llvm::FunctionAnalysisManager fam; + llvm::CGSCCAnalysisManager cgam; + llvm::ModuleAnalysisManager mam; + pass_builder.registerLoopAnalyses(lam); + pass_builder.registerFunctionAnalyses(fam); + pass_builder.registerCGSCCAnalyses(cgam); + pass_builder.registerModuleAnalyses(mam); + pass_builder.crossRegisterProxies(lam, fam, cgam, mam); + + llvm::ModulePassManager mpm; + llvm::InlineParams inline_params; + inline_params.DefaultThreshold = 250; + mpm.addPass(llvm::ModuleInlinerWrapperPass(inline_params)); + mpm.addPass(llvm::GlobalOptPass()); + mpm.addPass(llvm::GlobalDCEPass()); + // TODO(alex): Figure out what to do here. + // The new version of this pass only seems to have been added in LLVM 12. + // mpm.addPass(llvm::StripDeadDebugInfoPass()); + mpm.run(module, mam); + + llvm::FunctionPassManager fpm; + fpm.addPass(llvm::DCEPass()); + fpm.addPass(llvm::SinkingPass()); + fpm.addPass(llvm::NewGVNPass()); + fpm.addPass(llvm::SCCPPass()); + fpm.addPass(llvm::DSEPass()); + fpm.addPass(llvm::SROA()); + fpm.addPass(llvm::EarlyCSEPass()); + fpm.addPass(llvm::BDCEPass()); + fpm.addPass(llvm::SimplifyCFGPass()); + fpm.addPass(llvm::SinkingPass()); + fpm.addPass(llvm::SimplifyCFGPass()); + fpm.addPass(llvm::InstCombinePass()); auto error_manager_ptr = ITransformationErrorManager::Create(); auto &err_man = *error_manager_ptr.get(); - fpm.add(CreateSinkSelectionsIntoBranchTargets(err_man)); - fpm.add(CreateRemoveUnusedFPClassificationCalls()); - fpm.add(CreateRemoveDelaySlotIntrinsics()); - fpm.add(CreateRemoveErrorIntrinsics()); - fpm.add(CreateLowerRemillMemoryAccessIntrinsics()); - fpm.add(CreateRemoveCompilerBarriers()); - fpm.add(CreateLowerTypeHintIntrinsics()); - fpm.add(CreateInstructionFolderPass(err_man)); - fpm.add(llvm::createDeadCodeEliminationPass()); - fpm.add(CreateRecoverEntityUseInformation(err_man, lifter_context)); - fpm.add(CreateSinkSelectionsIntoBranchTargets(err_man)); - fpm.add(CreateRemoveTrivialPhisAndSelects()); - fpm.add(llvm::createDeadCodeEliminationPass()); - fpm.add(CreateRecoverStackFrameInformation(err_man, options)); - fpm.add(llvm::createSROAPass()); - fpm.add(CreateSplitStackFrameAtReturnAddress(err_man)); - fpm.add(llvm::createSROAPass()); + AddSinkSelectionsIntoBranchTargets(fpm, err_man); + AddRemoveUnusedFPClassificationCalls(fpm); + AddRemoveDelaySlotIntrinsics(fpm); + AddRemoveErrorIntrinsics(fpm); + AddLowerRemillMemoryAccessIntrinsics(fpm); + AddRemoveCompilerBarriers(fpm); + AddLowerTypeHintIntrinsics(fpm); + AddInstructionFolderPass(fpm, err_man); + fpm.addPass(llvm::DCEPass()); + AddRecoverEntityUseInformation(fpm, err_man, lifter_context); + AddSinkSelectionsIntoBranchTargets(fpm, err_man); + AddRemoveTrivialPhisAndSelects(fpm); + fpm.addPass(llvm::DCEPass()); + AddRecoverStackFrameInformation(fpm, err_man, options); + fpm.addPass(llvm::SROA()); + AddSplitStackFrameAtReturnAddress(fpm, err_man); + fpm.addPass(llvm::SROA()); // Sometimes we have a values in the form of (expr ^ 1) used as branch // conditions or other targets. Try to fix these to be CMPs, since it // makes code easier to read and analyze. This is a fairly narrow optimization // but it comes up often enough for lifted code. - fpm.add(CreateConvertXorToCmp()); + AddConvertXorToCmp(fpm); if (FLAGS_pointer_brighten_gas) { - fpm.add(CreateBrightenPointerOperations(FLAGS_pointer_brighten_gas)); + AddBrightenPointerOperations(fpm, FLAGS_pointer_brighten_gas); } - fpm.doInitialization(); for (auto &func : module) { - fpm.run(func); + fpm.run(func, fam); } - fpm.doFinalization(); // We can extend error handling here to provide more visibility // into what has happened @@ -183,14 +209,12 @@ void OptimizeModule(const EntityLifter &lifter_context, CHECK(!err_man.HasFatalError()); - fpm.add(CreateTransformRemillJumpIntrinsics(lifter_context)); - fpm.add(CreateRemoveRemillFunctionReturns(lifter_context)); - fpm.add(CreateLowerRemillUndefinedIntrinsics()); - fpm.doInitialization(); + AddTransformRemillJumpIntrinsics(fpm, lifter_context); + AddRemoveRemillFunctionReturns(fpm, lifter_context); + AddLowerRemillUndefinedIntrinsics(fpm); for (auto &func : module) { - fpm.run(func); + fpm.run(func, fam); } - fpm.doFinalization(); // Get rid of all final uses of `__anvill_pc`. if (auto anvill_pc = module.getGlobalVariable(::anvill::kSymbolicPCName)) { diff --git a/libraries/anvill_passes/include/anvill/Transforms.h b/libraries/anvill_passes/include/anvill/Transforms.h index e18701b2f..188f820f9 100644 --- a/libraries/anvill_passes/include/anvill/Transforms.h +++ b/libraries/anvill_passes/include/anvill/Transforms.h @@ -21,10 +21,10 @@ #include #include #include +#include namespace llvm { class Function; -class FunctionPass; } // namespace llvm namespace anvill { @@ -55,14 +55,14 @@ class EntityLifter; // // When this happens, we're better able to fold cross-references at the targets // of conditional branches. -llvm::FunctionPass *CreateSinkSelectionsIntoBranchTargets( - ITransformationErrorManager &error_manager); +void AddSinkSelectionsIntoBranchTargets( + llvm::FunctionPassManager &fpm, ITransformationErrorManager &error_manager); // Remill semantics sometimes contain compiler barriers (empty inline assembly // statements), especially related to floating point code (i.e. preventing // re-ordering of floating point operations so that we can capture the flags). // This pass eliminates those empty inline assembly statements. -llvm::FunctionPass *CreateRemoveCompilerBarriers(void); +void AddRemoveCompilerBarriers(llvm::FunctionPassManager &fpm); // Analyze `func` and determine if the function stores the return value of // the `llvm.returnaddress` intrinsic into an `alloca` (presumed to be the @@ -85,8 +85,8 @@ llvm::FunctionPass *CreateRemoveCompilerBarriers(void); // frame. This approach is very convenient, but comes at the cost of having // to do this particular transformation in order to recover more typical stack // frame structures. -llvm::FunctionPass *CreateSplitStackFrameAtReturnAddress( - ITransformationErrorManager &error_manager); +void AddSplitStackFrameAtReturnAddress( + llvm::FunctionPassManager &fpm, ITransformationErrorManager &error_manager); // Remove unused calls to floating point classification functions. Calls to // these functions are present in a bunch of FPU-related instruction semantics @@ -99,11 +99,11 @@ llvm::FunctionPass *CreateSplitStackFrameAtReturnAddress( // NOTE(pag): This pass must be applied before any kind of renaming of lifted // functions is performed, so that we don't accidentally remove // calls to classification functions present in the target binary. -llvm::FunctionPass *CreateRemoveUnusedFPClassificationCalls(void); +void AddRemoveUnusedFPClassificationCalls(llvm::FunctionPassManager &fpm); // Lowers the `__remill_read_memory_NN`, `__remill_write_memory_NN`, and the // various atomic read-modify-write variants into LLVM loads and stores. -llvm::FunctionPass *CreateLowerRemillMemoryAccessIntrinsics(void); +void AddLowerRemillMemoryAccessIntrinsics(llvm::FunctionPassManager &fpm); // Type information from prior lifting efforts, or from front-end tools // (e.g. Binary Ninja) is plumbed through the system by way of calls to // intrinsic functions such as `__anvill_type`. These function calls @@ -114,7 +114,7 @@ llvm::FunctionPass *CreateLowerRemillMemoryAccessIntrinsics(void); // // These function calls need to be removed/lowered into `inttoptr` or `bitcast` // instructions. -llvm::FunctionPass *CreateLowerTypeHintIntrinsics(void); +void AddLowerTypeHintIntrinsics(llvm::FunctionPassManager &fpm); // Anvill-lifted bitcode operates at a very low level, swapping between integer // and pointer representations. It is typically for just-lifted bitcode to @@ -134,7 +134,8 @@ llvm::FunctionPass *CreateLowerTypeHintIntrinsics(void); // // This function attempts to apply a battery of pattern-based transforms to // brighten integer operations into pointer operations. -llvm::FunctionPass *CreateBrightenPointerOperations(unsigned max_gas = 250); +void AddBrightenPointerOperations(llvm::FunctionPassManager &fpm, + unsigned max_gas = 250); // Transforms the bitcode to eliminate calls to `__remill_function_return`, // where appropriate. This will not succeed for all architectures, but is @@ -163,8 +164,8 @@ llvm::FunctionPass *CreateBrightenPointerOperations(unsigned max_gas = 250); // // NOTE(pag): This pass should be applied as late as possible, as the call to // `__remill_function_return` depends upon the memory pointer. -llvm::FunctionPass * -CreateRemoveRemillFunctionReturns(const EntityLifter &lifter); +void AddRemoveRemillFunctionReturns(llvm::FunctionPassManager &fpm, + const EntityLifter &lifter); // This function pass makes use of the `__anvill_sp` usages to create an // `llvm::StructType` that acts as a stack frame. This initial stack frame @@ -175,9 +176,9 @@ CreateRemoveRemillFunctionReturns(const EntityLifter &lifter); // to eliminate the stack frame, then to enable splitting of the stack from // into components (see `CreateSplitStackFrameAtReturnAddress`) such that // SROA can apply to the arguments and return address components. -llvm::FunctionPass * -CreateRecoverStackFrameInformation(ITransformationErrorManager &error_manager, - const LifterOptions &options); +void AddRecoverStackFrameInformation(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager, + const LifterOptions &options); // Anvill-lifted code is full of references to constant expressions related // to `__anvill_pc`. These constant expressions exist to "taint" values as @@ -189,9 +190,9 @@ CreateRecoverStackFrameInformation(ITransformationErrorManager &error_manager, // other entitities. We say opportunistic because that pass is not guaranteed // to replace all such references, and will in fact leave references around // for later passes to benefit from. -llvm::FunctionPass * -CreateRecoverEntityUseInformation(ITransformationErrorManager &error_manager, - const EntityLifter &lifter); +void AddRecoverEntityUseInformation(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager, + const EntityLifter &lifter); // Some machine code instructions explicitly introduce undefined values / // behavior. Often, this is a result of the CPUs of different steppings of @@ -208,19 +209,19 @@ CreateRecoverEntityUseInformation(ITransformationErrorManager &error_manager, // // This pass exists to do the lowering to `undef` values, and should be run // as late as possible. -llvm::FunctionPass *CreateLowerRemillUndefinedIntrinsics(void); +void AddLowerRemillUndefinedIntrinsics(llvm::FunctionPassManager &fpm); // This function pass will attempt to fold the following instruction // combinations: // {SelectInst, PHINode}/{BinaryOperator, CastInst, GetElementPtrInst} -llvm::FunctionPass * -CreateInstructionFolderPass(ITransformationErrorManager &error_manager); +void AddInstructionFolderPass(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager); // Removes trivial PHI and select nodes. These are PHI and select nodes whose // incoming values or true/false values match. This can happen as a result of // the instruction folding pass that hoists and folds values up through selects // and PHI nodes, followed by the select sinking pass, which pushes values down. -llvm::FunctionPass *CreateRemoveTrivialPhisAndSelects(void); +void AddRemoveTrivialPhisAndSelects(llvm::FunctionPassManager &fpm); // The pass transforms bitcode to replace the calls to `__remill_jump` into // `__remill_function_return` if a value returned by `llvm.returnaddress`, or @@ -235,8 +236,8 @@ llvm::FunctionPass *CreateRemoveTrivialPhisAndSelects(void); // NOTE: The pass should be run as late as possible in the list but before // `RemoveRemillFunctionReturns` transform -llvm::FunctionPass * -CreateTransformRemillJumpIntrinsics(const EntityLifter &lifter); +void AddTransformRemillJumpIntrinsics(llvm::FunctionPassManager &fpm, + const EntityLifter &lifter); // Finds values in the form of: // %cmp = icmp eq val1, val2 @@ -252,14 +253,14 @@ CreateTransformRemillJumpIntrinsics(const EntityLifter &lifter); // with xors is more difficult to analyze and for a human to read // This pass should only work on boolean values, and handle when those are used // in Branches and Selects -llvm::FunctionPass *CreateConvertXorToCmp(void); +void AddConvertXorToCmp(llvm::FunctionPassManager &fpm); // Removes calls to `__remill_delay_slot_begin` and `__remill_delay_slot_end`. // These calls surround the lifted versions of delayed instructions, to signal // their location in the bitcode. -llvm::FunctionPass *CreateRemoveDelaySlotIntrinsics(void); +void AddRemoveDelaySlotIntrinsics(llvm::FunctionPassManager &fpm); // Removes calls to `__remill_error`. -llvm::FunctionPass *CreateRemoveErrorIntrinsics(void); +void AddRemoveErrorIntrinsics(llvm::FunctionPassManager &fpm); } // namespace anvill diff --git a/libraries/anvill_passes/src/BaseFunctionPass.h b/libraries/anvill_passes/src/BaseFunctionPass.h index 3bc92532e..91c2df8ee 100644 --- a/libraries/anvill_passes/src/BaseFunctionPass.h +++ b/libraries/anvill_passes/src/BaseFunctionPass.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -50,10 +51,7 @@ enum class BaseFunctionPassErrorCode { }; template -class BaseFunctionPass : public llvm::FunctionPass { - - // Function pass identifier; `&ID` needs to be unique! - static char ID; +class BaseFunctionPass : public llvm::PassInfoMixin { // Current module. llvm::Module *module{nullptr}; @@ -79,7 +77,8 @@ class BaseFunctionPass : public llvm::FunctionPass { virtual ~BaseFunctionPass(void) = default; // Function pass entry point, called by LLVM - virtual bool runOnFunction(llvm::Function &function) final override; + llvm::PreservedAnalyses run(llvm::Function &function, + llvm::FunctionAnalysisManager &fam); // Returns true if this instruction references the stack pointer static bool @@ -124,18 +123,15 @@ class BaseFunctionPass : public llvm::FunctionPass { llvm::StringRef name); }; -template -char BaseFunctionPass::ID = '\0'; - template BaseFunctionPass::BaseFunctionPass( ITransformationErrorManager &error_manager_) - : llvm::FunctionPass(ID), - error_manager(error_manager_) {} + : error_manager(error_manager_) {} template -bool BaseFunctionPass::runOnFunction( - llvm::Function &function_) { +llvm::PreservedAnalyses +BaseFunctionPass::run(llvm::Function &function_, + llvm::FunctionAnalysisManager &) { function = &function_; module = function->getParent(); original_function_ir = GetFunctionIR(*function); @@ -223,7 +219,7 @@ void BaseFunctionPass::EmitError(SeverityType severity, llvm::Instruction *instr) { TransformationError error; - error.pass_name = getPassName().str(); + error.pass_name = llvm::PassInfoMixin::name().str(); error.severity = severity; error.error_code = EnumValueToString(error_code); error.message = message; diff --git a/libraries/anvill_passes/src/BrightenPointerOperations.cpp b/libraries/anvill_passes/src/BrightenPointerOperations.cpp index e5659fe99..69bdd96f3 100644 --- a/libraries/anvill_passes/src/BrightenPointerOperations.cpp +++ b/libraries/anvill_passes/src/BrightenPointerOperations.cpp @@ -20,9 +20,10 @@ #include #include #include -#include #include +#include #include +#include #include #include @@ -33,23 +34,20 @@ namespace anvill { -char PointerLifterPass::ID = '\0'; +PointerLifterPass::PointerLifterPass(unsigned max_gas_) : max_gas(max_gas_) {} -PointerLifterPass::PointerLifterPass(unsigned max_gas_) - : FunctionPass(ID), - max_gas(max_gas_) {} - -bool PointerLifterPass::runOnFunction(llvm::Function &f) { +llvm::PreservedAnalyses +PointerLifterPass::run(llvm::Function &f, llvm::FunctionAnalysisManager &fam) { // f.print(llvm::errs(), nullptr); PointerLifter lifter(&f, max_gas); - lifter.LiftFunction(f); + lifter.LiftFunction(f, fam); // f.print(llvm::errs(), nullptr); // TODO (Carson) have an analysis function which determines modifications // Then use lift function to run those modifications - // Can return true/false depending on what was modified - return true; + // Can return all/none depending on what was modified + return llvm::PreservedAnalyses::none(); } PointerLifter::PointerLifter(llvm::Function *func_, unsigned max_gas_) @@ -1012,7 +1010,8 @@ updated values are added into the next_worklist. Pointer lifting for a function is done when we reach a fixed point, when the next_worklist is empty. */ -void PointerLifter::LiftFunction(llvm::Function &func) { +void PointerLifter::LiftFunction(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { std::vector worklist; std::vector gep_list; @@ -1033,11 +1032,9 @@ void PointerLifter::LiftFunction(llvm::Function &func) { } } // Deadcode remove stale geps. - llvm::legacy::FunctionPassManager fpm(mod); - fpm.add(llvm::createDeadCodeEliminationPass()); - fpm.doInitialization(); - fpm.run(func); - fpm.doFinalization(); + llvm::FunctionPassManager fpm; + fpm.addPass(llvm::DCEPass()); + fpm.run(func, fam); made_progress = true; for (auto i = 0u; i < max_gas && made_progress; ++i) { @@ -1089,9 +1086,7 @@ void PointerLifter::LiftFunction(llvm::Function &func) { next_inferred_types.clear(); to_remove.clear(); - fpm.doInitialization(); - fpm.run(func); - fpm.doFinalization(); + fpm.run(func, fam); } } @@ -1113,8 +1108,9 @@ void PointerLifter::LiftFunction(llvm::Function &func) { // // This function attempts to apply a battery of pattern-based transforms to // brighten integer operations into pointer operations. -llvm::FunctionPass *CreateBrightenPointerOperations(unsigned max_gas) { - return new PointerLifterPass(max_gas ? max_gas : 250u); +void AddBrightenPointerOperations(llvm::FunctionPassManager &fpm, + unsigned max_gas) { + fpm.addPass(PointerLifterPass(max_gas ? max_gas : 250u)); } } // namespace anvill diff --git a/libraries/anvill_passes/src/BrightenPointerOperations.h b/libraries/anvill_passes/src/BrightenPointerOperations.h index f58d37a65..7f891fa01 100644 --- a/libraries/anvill_passes/src/BrightenPointerOperations.h +++ b/libraries/anvill_passes/src/BrightenPointerOperations.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include @@ -44,14 +44,14 @@ namespace anvill { class CrossReferenceResolver; -class PointerLifterPass final : public llvm::FunctionPass { +class PointerLifterPass final : public llvm::PassInfoMixin { public: explicit PointerLifterPass(unsigned max_gas_); - bool runOnFunction(llvm::Function &f) final; + llvm::PreservedAnalyses run(llvm::Function &f, + llvm::FunctionAnalysisManager &fam); private: - static char ID; const unsigned max_gas; }; @@ -77,7 +77,7 @@ class PointerLifter std::pair visitReturnInst(llvm::ReturnInst& inst); std::pair visitStoreInst(llvm::StoreInst& store); std::pair visitAllocaInst(llvm::AllocaInst& alloca); - + std::pair visitSExtInst(llvm::SExtInst& inst); std::pair visitZExtInst(llvm::ZExtInst& inst); @@ -100,7 +100,7 @@ class PointerLifter llvm::Value *offset, llvm::Type *t) const; // Driver method - void LiftFunction(llvm::Function &func); + void LiftFunction(llvm::Function &func, llvm::FunctionAnalysisManager &fam); private: // Maximum number of iterations that `LiftFunction` is allowed to perform. diff --git a/libraries/anvill_passes/src/ConvertXorToCmp.cpp b/libraries/anvill_passes/src/ConvertXorToCmp.cpp index a2dd3fbea..ff1ae5a62 100644 --- a/libraries/anvill_passes/src/ConvertXorToCmp.cpp +++ b/libraries/anvill_passes/src/ConvertXorToCmp.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -31,18 +31,12 @@ namespace anvill { namespace { -class ConvertXorToCmp final : public llvm::FunctionPass { +class ConvertXorToCmp final : public llvm::PassInfoMixin { public: - ConvertXorToCmp(void) : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &func) override; - - private: - static char ID; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); }; -char ConvertXorToCmp::ID = '\0'; - // If the operator (op) is between an ICmpInst and a ConstantInt, // return a tuple representing the ICmpInst and ConstantInt // with tuple[0] holding the ICmpInst. @@ -78,7 +72,8 @@ static llvm::Value *negateCmpPredicate(llvm::ICmpInst *cmp) { return ir.CreateICmp(new_pred, cmp->getOperand(0), cmp->getOperand(1)); } -bool ConvertXorToCmp::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +ConvertXorToCmp::run(llvm::Function &func, llvm::FunctionAnalysisManager &fam) { std::vector xors; for (auto &inst : llvm::instructions(func)) { @@ -225,7 +220,8 @@ bool ConvertXorToCmp::runOnFunction(llvm::Function &func) { LOG(INFO) << "ConvertXorToCmp: replaced " << replaced_items << " xors with negated comparisons"; - return changed; + return changed ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); } } // namespace @@ -236,8 +232,8 @@ bool ConvertXorToCmp::runOnFunction(llvm::Function &func) { // (left !OP right) // this makes the output more natural for humans and computers to reason about // This problem comes up a fair bit due to how some instruction semantics compute carry/parity/etc bits -llvm::FunctionPass *CreateConvertXorToCmp(void) { - return new ConvertXorToCmp; +void AddConvertXorToCmp(llvm::FunctionPassManager &fpm) { + fpm.addPass(ConvertXorToCmp()); } } // namespace anvill diff --git a/libraries/anvill_passes/src/InstructionFolderPass.cpp b/libraries/anvill_passes/src/InstructionFolderPass.cpp index 836553a00..5b5a5c084 100644 --- a/libraries/anvill_passes/src/InstructionFolderPass.cpp +++ b/libraries/anvill_passes/src/InstructionFolderPass.cpp @@ -165,14 +165,14 @@ InstructionFolderPass::InstructionFolderPass( : BaseFunctionPass(error_manager) {} -InstructionFolderPass * -InstructionFolderPass::Create(ITransformationErrorManager &error_manager) { - return new InstructionFolderPass(error_manager); +void InstructionFolderPass::Add(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager) { + fpm.addPass(InstructionFolderPass(error_manager)); } -bool InstructionFolderPass::Run(llvm::Function &function) { +llvm::PreservedAnalyses InstructionFolderPass::Run(llvm::Function &function) { if (function.isDeclaration()) { - return false; + return llvm::PreservedAnalyses::all(); } dt.reset(new llvm::DominatorTree(function)); @@ -225,11 +225,8 @@ bool InstructionFolderPass::Run(llvm::Function &function) { } } - return function_changed; -} - -llvm::StringRef InstructionFolderPass::getPassName(void) const { - return llvm::StringRef("InstructionFolderPass"); + return function_changed ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); } bool InstructionFolderPass::FoldSelectInstruction( @@ -783,9 +780,9 @@ bool InstructionFolderPass::FoldPHINodeWithGEPInst( return true; } -llvm::FunctionPass * -CreateInstructionFolderPass(ITransformationErrorManager &error_manager) { - return InstructionFolderPass::Create(error_manager); +void AddInstructionFolderPass(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager) { + InstructionFolderPass::Add(fpm, error_manager); } } // namespace anvill diff --git a/libraries/anvill_passes/src/InstructionFolderPass.h b/libraries/anvill_passes/src/InstructionFolderPass.h index 9251fcecd..64d12297c 100644 --- a/libraries/anvill_passes/src/InstructionFolderPass.h +++ b/libraries/anvill_passes/src/InstructionFolderPass.h @@ -27,18 +27,16 @@ class InstructionFolderPass final : public BaseFunctionPass { public: explicit InstructionFolderPass(ITransformationErrorManager &error_manager); + InstructionFolderPass(InstructionFolderPass &&) = default; virtual ~InstructionFolderPass(void) override = default; // Creates a new InstructionFolderPass object - static InstructionFolderPass * - Create(ITransformationErrorManager &error_manager); + static void Add(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager); // Function pass entry point - bool Run(llvm::Function &function); - - // Returns the pass name - virtual llvm::StringRef getPassName(void) const override; + llvm::PreservedAnalyses Run(llvm::Function &function); // Folds `Select` instructions interacting with `CastInst`, // `BinaryOperator` and `GetElementPtrInst` instructions diff --git a/libraries/anvill_passes/src/LowerRemillMemoryAccessIntrinsics.cpp b/libraries/anvill_passes/src/LowerRemillMemoryAccessIntrinsics.cpp index 756d81206..8c1d0bf7f 100644 --- a/libraries/anvill_passes/src/LowerRemillMemoryAccessIntrinsics.cpp +++ b/libraries/anvill_passes/src/LowerRemillMemoryAccessIntrinsics.cpp @@ -28,19 +28,13 @@ namespace anvill { namespace { -class LowerRemillMemoryAccessIntrinsics final : public llvm::FunctionPass { +class LowerRemillMemoryAccessIntrinsics final + : public llvm::PassInfoMixin { public: - LowerRemillMemoryAccessIntrinsics(void) : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &func) final; - - private: - static char ID; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); }; -char LowerRemillMemoryAccessIntrinsics::ID = '\0'; - - // Lower a memory read intrinsic into a `load` instruction. static void ReplaceMemReadOp(llvm::CallBase *call_inst, llvm::Type *val_type) { auto addr = call_inst->getArgOperand(1); @@ -111,7 +105,9 @@ static bool ReplaceMemoryOp(llvm::CallBase *call) { } // Try to lower remill memory access intrinsics. -bool LowerRemillMemoryAccessIntrinsics::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +LowerRemillMemoryAccessIntrinsics::run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { auto calls = FindFunctionCalls(func, [](llvm::CallBase *call) -> bool { const auto func = call->getCalledFunction(); if (!func) { @@ -129,15 +125,15 @@ bool LowerRemillMemoryAccessIntrinsics::runOnFunction(llvm::Function &func) { ret = ReplaceMemoryOp(call) || ret; } - return ret; + return ret ? llvm::PreservedAnalyses::none() : llvm::PreservedAnalyses::all(); } } // namespace // Lowers the `__remill_read_memory_NN`, `__remill_write_memory_NN`, and the // various atomic read-modify-write variants into LLVM loads and stores. -llvm::FunctionPass *CreateLowerRemillMemoryAccessIntrinsics(void) { - return new LowerRemillMemoryAccessIntrinsics; +void AddLowerRemillMemoryAccessIntrinsics(llvm::FunctionPassManager &fpm) { + fpm.addPass(LowerRemillMemoryAccessIntrinsics()); } } // namespace anvill diff --git a/libraries/anvill_passes/src/LowerRemillUndefinedIntrinsics.cpp b/libraries/anvill_passes/src/LowerRemillUndefinedIntrinsics.cpp index b327fe398..cc9f511d7 100644 --- a/libraries/anvill_passes/src/LowerRemillUndefinedIntrinsics.cpp +++ b/libraries/anvill_passes/src/LowerRemillUndefinedIntrinsics.cpp @@ -17,30 +17,26 @@ #include #include -#include #include +#include #include -#include +#include #include namespace anvill { namespace { -class LowerRemillUndefinedIntrinsics final : public llvm::FunctionPass { +class LowerRemillUndefinedIntrinsics final + : public llvm::PassInfoMixin { public: - LowerRemillUndefinedIntrinsics(void) - : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &func) override; - - private: - static char ID; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); }; -char LowerRemillUndefinedIntrinsics::ID = '\0'; - -bool LowerRemillUndefinedIntrinsics::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +LowerRemillUndefinedIntrinsics::run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { std::vector calls; for (auto &inst : llvm::instructions(func)) { @@ -59,7 +55,8 @@ bool LowerRemillUndefinedIntrinsics::runOnFunction(llvm::Function &func) { changed = true; } - return changed; + return changed ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); } } // namespace @@ -79,8 +76,8 @@ bool LowerRemillUndefinedIntrinsics::runOnFunction(llvm::Function &func) { // // This pass exists to do the lowering to `undef` values, and should be run // as late as possible. -llvm::FunctionPass *CreateLowerRemillUndefinedIntrinsics(void) { - return new LowerRemillUndefinedIntrinsics; +void AddLowerRemillUndefinedIntrinsics(llvm::FunctionPassManager &fpm) { + fpm.addPass(LowerRemillUndefinedIntrinsics()); } } // namespace anvill diff --git a/libraries/anvill_passes/src/LowerTypeHintIntrinsics.cpp b/libraries/anvill_passes/src/LowerTypeHintIntrinsics.cpp index 9407174d0..7663a67e5 100644 --- a/libraries/anvill_passes/src/LowerTypeHintIntrinsics.cpp +++ b/libraries/anvill_passes/src/LowerTypeHintIntrinsics.cpp @@ -16,31 +16,27 @@ */ #include -#include -#include #include +#include +#include #include -#include +#include #include namespace anvill { namespace { -class LowerTypeHintIntrinsics final : public llvm::FunctionPass { +class LowerTypeHintIntrinsics final + : public llvm::PassInfoMixin { public: - LowerTypeHintIntrinsics(void) - : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &func) override; - - private: - static char ID; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); }; -char LowerTypeHintIntrinsics::ID = '\0'; - -bool LowerTypeHintIntrinsics::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +LowerTypeHintIntrinsics::run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { std::vector calls; for (auto &inst : llvm::instructions(func)) { @@ -68,7 +64,8 @@ bool LowerTypeHintIntrinsics::runOnFunction(llvm::Function &func) { } } - return changed; + return changed ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); } } // namespace @@ -83,8 +80,8 @@ bool LowerTypeHintIntrinsics::runOnFunction(llvm::Function &func) { // // These function calls need to be removed/lowered into `inttoptr` or `bitcast` // instructions. -llvm::FunctionPass *CreateLowerTypeHintIntrinsics(void) { - return new LowerTypeHintIntrinsics; +void AddLowerTypeHintIntrinsics(llvm::FunctionPassManager &fpm) { + fpm.addPass(LowerTypeHintIntrinsics()); } } // namespace anvill diff --git a/libraries/anvill_passes/src/RecoverEntityUseInformation.cpp b/libraries/anvill_passes/src/RecoverEntityUseInformation.cpp index 12250ebd8..844f936ef 100644 --- a/libraries/anvill_passes/src/RecoverEntityUseInformation.cpp +++ b/libraries/anvill_passes/src/RecoverEntityUseInformation.cpp @@ -29,20 +29,21 @@ namespace anvill { -RecoverEntityUseInformation * -RecoverEntityUseInformation::Create(ITransformationErrorManager &error_manager, - const EntityLifter &lifter) { - return new RecoverEntityUseInformation(error_manager, lifter); +void RecoverEntityUseInformation::Add( + llvm::FunctionPassManager &fpm, ITransformationErrorManager &error_manager, + const EntityLifter &lifter) { + fpm.addPass(RecoverEntityUseInformation(error_manager, lifter)); } -bool RecoverEntityUseInformation::Run(llvm::Function &function) { +llvm::PreservedAnalyses +RecoverEntityUseInformation::Run(llvm::Function &function) { if (function.isDeclaration()) { - return false; + return llvm::PreservedAnalyses::all(); } auto uses = EnumeratePossibleEntityUsages(function); if (uses.empty()) { - return false; + return llvm::PreservedAnalyses::all(); } // It is now time to patch the function. This method will take the stack @@ -55,14 +56,10 @@ bool RecoverEntityUseInformation::Run(llvm::Function &function) { "Function transformation has failed and there was a failure recovering " "an entity reference"); - return false; + return llvm::PreservedAnalyses::all(); } - return true; -} - -llvm::StringRef RecoverEntityUseInformation::getPassName(void) const { - return llvm::StringRef("RecoverEntityUseInformation"); + return llvm::PreservedAnalyses::none(); } EntityUsages RecoverEntityUseInformation::EnumeratePossibleEntityUsages( @@ -245,10 +242,10 @@ RecoverEntityUseInformation::RecoverEntityUseInformation( // other entitities. We say opportunistic because that pass is not guaranteed // to replace all such references, and will in fact leave references around // for later passes to benefit from. -llvm::FunctionPass * -CreateRecoverEntityUseInformation(ITransformationErrorManager &error_manager, - const EntityLifter &lifter) { - return RecoverEntityUseInformation::Create(error_manager, lifter); +void AddRecoverEntityUseInformation(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager, + const EntityLifter &lifter) { + RecoverEntityUseInformation::Add(fpm, error_manager, lifter); } } // namespace anvill diff --git a/libraries/anvill_passes/src/RecoverEntityUseInformation.h b/libraries/anvill_passes/src/RecoverEntityUseInformation.h index ba1068911..497f79a6f 100644 --- a/libraries/anvill_passes/src/RecoverEntityUseInformation.h +++ b/libraries/anvill_passes/src/RecoverEntityUseInformation.h @@ -69,15 +69,12 @@ class RecoverEntityUseInformation final public: // Creates a new RecoverStackFrameInformation object - static RecoverEntityUseInformation * - Create(ITransformationErrorManager &error_manager, - const EntityLifter &lifter); + static void Add(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager, + const EntityLifter &lifter); // Function pass entry point - bool Run(llvm::Function &function); - - // Returns the pass name - virtual llvm::StringRef getPassName(void) const override; + llvm::PreservedAnalyses Run(llvm::Function &function); // Enumerates some of the possible entity usages that are isolated to // specific instruction operand uses. diff --git a/libraries/anvill_passes/src/RecoverStackFrameInformation.cpp b/libraries/anvill_passes/src/RecoverStackFrameInformation.cpp index 3bd6d3acc..4653edd1b 100644 --- a/libraries/anvill_passes/src/RecoverStackFrameInformation.cpp +++ b/libraries/anvill_passes/src/RecoverStackFrameInformation.cpp @@ -27,15 +27,16 @@ #include "Utils.h" namespace anvill { -RecoverStackFrameInformation * -RecoverStackFrameInformation::Create(ITransformationErrorManager &error_manager, - const LifterOptions &options) { - return new RecoverStackFrameInformation(error_manager, options); +void RecoverStackFrameInformation::Add( + llvm::FunctionPassManager &fpm, ITransformationErrorManager &error_manager, + const LifterOptions &options) { + fpm.addPass(RecoverStackFrameInformation(error_manager, options)); } -bool RecoverStackFrameInformation::Run(llvm::Function &function) { +llvm::PreservedAnalyses +RecoverStackFrameInformation::Run(llvm::Function &function) { if (function.isDeclaration()) { - return false; + return llvm::PreservedAnalyses::all(); } // Analyze the stack frame first, enumerating the instructions referencing @@ -45,12 +46,12 @@ bool RecoverStackFrameInformation::Run(llvm::Function &function) { EmitError(SeverityType::Error, stack_frame_analysis_res.Error(), "The stack frame analysis has failed"); - return false; + return llvm::PreservedAnalyses::all(); } auto stack_frame_analysis = stack_frame_analysis_res.TakeValue(); if (stack_frame_analysis.size == 0) { - return false; + return llvm::PreservedAnalyses::all(); } // It is now time to patch the function. This method will take the stack @@ -65,7 +66,7 @@ bool RecoverStackFrameInformation::Run(llvm::Function &function) { SeverityType::Fatal, update_func_res.Error(), "Function transformation has failed and the stack could not be recovered"); - return false; + return llvm::PreservedAnalyses::all(); } // Analyze the __anvill_sp usage again; this time, the resulting @@ -75,7 +76,7 @@ bool RecoverStackFrameInformation::Run(llvm::Function &function) { EmitError(SeverityType::Fatal, second_stack_frame_uses_res.Error(), "The post-transformation stack frame analysis has failed"); - return false; + return llvm::PreservedAnalyses::all(); } auto second_stack_frame_uses = second_stack_frame_uses_res.TakeValue(); @@ -86,11 +87,7 @@ bool RecoverStackFrameInformation::Run(llvm::Function &function) { "The stack frame recovery did not replace all the possible __anvill_sp uses"); } - return true; -} - -llvm::StringRef RecoverStackFrameInformation::getPassName(void) const { - return llvm::StringRef("RecoverStackFrameInformation"); + return llvm::PreservedAnalyses::none(); } Result @@ -431,10 +428,10 @@ RecoverStackFrameInformation::RecoverStackFrameInformation( : BaseFunctionPass(error_manager), options(options) {} -llvm::FunctionPass * -CreateRecoverStackFrameInformation(ITransformationErrorManager &error_manager, - const LifterOptions &options) { - return RecoverStackFrameInformation::Create(error_manager, options); +void AddRecoverStackFrameInformation(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager, + const LifterOptions &options) { + RecoverStackFrameInformation::Add(fpm, error_manager, options); } } // namespace anvill diff --git a/libraries/anvill_passes/src/RecoverStackFrameInformation.h b/libraries/anvill_passes/src/RecoverStackFrameInformation.h index 39aefb81a..3419b28bf 100644 --- a/libraries/anvill_passes/src/RecoverStackFrameInformation.h +++ b/libraries/anvill_passes/src/RecoverStackFrameInformation.h @@ -89,15 +89,12 @@ class RecoverStackFrameInformation final public: // Creates a new RecoverStackFrameInformation object - static RecoverStackFrameInformation * - Create(ITransformationErrorManager &error_manager, - const LifterOptions &options); + static void Add(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager, + const LifterOptions &options); // Function pass entry point - bool Run(llvm::Function &function); - - // Returns the pass name - virtual llvm::StringRef getPassName(void) const override; + llvm::PreservedAnalyses Run(llvm::Function &function); // Enumerates all the store and load instructions that reference // the stack diff --git a/libraries/anvill_passes/src/RemoveCompilerBarriers.cpp b/libraries/anvill_passes/src/RemoveCompilerBarriers.cpp index ff253fca3..0db0ee3f0 100644 --- a/libraries/anvill_passes/src/RemoveCompilerBarriers.cpp +++ b/libraries/anvill_passes/src/RemoveCompilerBarriers.cpp @@ -25,20 +25,17 @@ namespace anvill { namespace { -class RemoveCompilerBarriers final : public llvm::FunctionPass { +class RemoveCompilerBarriers final + : public llvm::PassInfoMixin { public: - RemoveCompilerBarriers(void) : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &func) final; - - private: - static char ID; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); }; -char RemoveCompilerBarriers::ID = '\0'; - // Try to lower remill memory access intrinsics. -bool RemoveCompilerBarriers::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +RemoveCompilerBarriers::run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { std::vector to_remove; for (llvm::BasicBlock &block : func) { @@ -91,7 +88,8 @@ bool RemoveCompilerBarriers::runOnFunction(llvm::Function &func) { call_inst->eraseFromParent(); } - return !to_remove.empty(); + return !to_remove.empty() ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); } } // namespace @@ -100,8 +98,8 @@ bool RemoveCompilerBarriers::runOnFunction(llvm::Function &func) { // statements), especially related to floating point code (i.e. preventing // re-ordering of floating point operations so that we can capture the flags). // This pass eliminates those empty inline assembly statements. -llvm::FunctionPass *CreateRemoveCompilerBarriers(void) { - return new RemoveCompilerBarriers; +void AddRemoveCompilerBarriers(llvm::FunctionPassManager &fpm) { + fpm.addPass(RemoveCompilerBarriers()); } } // namespace anvill diff --git a/libraries/anvill_passes/src/RemoveDelaySlotIntrinsics.cpp b/libraries/anvill_passes/src/RemoveDelaySlotIntrinsics.cpp index 7d012436d..7740e3949 100644 --- a/libraries/anvill_passes/src/RemoveDelaySlotIntrinsics.cpp +++ b/libraries/anvill_passes/src/RemoveDelaySlotIntrinsics.cpp @@ -28,26 +28,23 @@ namespace anvill { namespace { -class RemoveDelaySlotIntrinsics final : public llvm::FunctionPass { +class RemoveDelaySlotIntrinsics final + : public llvm::PassInfoMixin { public: - RemoveDelaySlotIntrinsics(void) : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &func) final; - - private: - static char ID; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); }; -char RemoveDelaySlotIntrinsics::ID = '\0'; - // Try to lower remill memory access intrinsics. -bool RemoveDelaySlotIntrinsics::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +RemoveDelaySlotIntrinsics::run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { auto module = func.getParent(); auto begin = module->getFunction("__remill_delay_slot_begin"); auto end = module->getFunction("__remill_delay_slot_end"); if (!begin && !end) { - return false; + return llvm::PreservedAnalyses::all(); } auto calls = FindFunctionCalls(func, [=](llvm::CallBase *call) -> bool { @@ -61,14 +58,15 @@ bool RemoveDelaySlotIntrinsics::runOnFunction(llvm::Function &func) { call->eraseFromParent(); } - return !calls.empty(); + return !calls.empty() ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); } } // namespace // Removes calls to `__remill_delay_slot_begin` and `__remill_delay_slot_end`. -llvm::FunctionPass *CreateRemoveDelaySlotIntrinsics(void) { - return new RemoveDelaySlotIntrinsics; +void AddRemoveDelaySlotIntrinsics(llvm::FunctionPassManager &fpm) { + fpm.addPass(RemoveDelaySlotIntrinsics()); } } // namespace anvill diff --git a/libraries/anvill_passes/src/RemoveErrorIntrinsics.cpp b/libraries/anvill_passes/src/RemoveErrorIntrinsics.cpp index a6430a172..01dcb958d 100644 --- a/libraries/anvill_passes/src/RemoveErrorIntrinsics.cpp +++ b/libraries/anvill_passes/src/RemoveErrorIntrinsics.cpp @@ -30,25 +30,22 @@ namespace anvill { namespace { -class RemoveErrorIntrinsics final : public llvm::FunctionPass { +class RemoveErrorIntrinsics final + : public llvm::PassInfoMixin { public: - RemoveErrorIntrinsics(void) : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &func) final; - - private: - static char ID; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); }; -char RemoveErrorIntrinsics::ID = '\0'; - // Try to lower remill error intrinsics. -bool RemoveErrorIntrinsics::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +RemoveErrorIntrinsics::run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { auto module = func.getParent(); auto error = module->getFunction("__remill_error"); if (!error) { - return false; + return llvm::PreservedAnalyses::all(); } auto calls = FindFunctionCalls(func, [=](llvm::CallBase *call) -> bool { @@ -174,14 +171,15 @@ bool RemoveErrorIntrinsics::runOnFunction(llvm::Function &func) { } } - return !removed.empty(); + return !removed.empty() ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); } } // namespace // Removes calls to `__remill_error`. -llvm::FunctionPass *CreateRemoveErrorIntrinsics(void) { - return new RemoveErrorIntrinsics; +void AddRemoveErrorIntrinsics(llvm::FunctionPassManager &fpm) { + fpm.addPass(RemoveErrorIntrinsics()); } } // namespace anvill diff --git a/libraries/anvill_passes/src/RemoveRemillFunctionReturns.cpp b/libraries/anvill_passes/src/RemoveRemillFunctionReturns.cpp index 093029199..229b15db9 100644 --- a/libraries/anvill_passes/src/RemoveRemillFunctionReturns.cpp +++ b/libraries/anvill_passes/src/RemoveRemillFunctionReturns.cpp @@ -60,24 +60,22 @@ enum ReturnAddressResult { kUnclassifiableReturnAddress }; -class RemoveRemillFunctionReturns final : public llvm::FunctionPass { +class RemoveRemillFunctionReturns final + : public llvm::PassInfoMixin { public: RemoveRemillFunctionReturns(const EntityLifter &lifter_) - : llvm::FunctionPass(ID), - xref_resolver(lifter_) {} + : xref_resolver(lifter_) {} - bool runOnFunction(llvm::Function &func) final; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); private: ReturnAddressResult QueryReturnAddress(llvm::Module *module, llvm::Value *val) const; - static char ID; const CrossReferenceResolver xref_resolver; }; -char RemoveRemillFunctionReturns::ID = '\0'; - // Returns `true` if `val` is a return address. ReturnAddressResult RemoveRemillFunctionReturns::QueryReturnAddress( llvm::Module *module, llvm::Value *val) const { @@ -238,7 +236,9 @@ static void OverwriteReturnAddress( // Try to identify the patterns of `__remill_function_call` that we can // remove. -bool RemoveRemillFunctionReturns::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +RemoveRemillFunctionReturns::run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { const auto module = func.getParent(); std::vector matches_pattern; @@ -283,7 +283,7 @@ bool RemoveRemillFunctionReturns::runOnFunction(llvm::Function &func) { } } - return ret; + return ret ? llvm::PreservedAnalyses::none() : llvm::PreservedAnalyses::all(); } } // namespace @@ -315,9 +315,9 @@ bool RemoveRemillFunctionReturns::runOnFunction(llvm::Function &func) { // // NOTE(pag): This pass should be applied as late as possible, as the call to // `__remill_function_return` depends upon the memory pointer. -llvm::FunctionPass *CreateRemoveRemillFunctionReturns( - const EntityLifter &lifter) { - return new RemoveRemillFunctionReturns(lifter); +void AddRemoveRemillFunctionReturns(llvm::FunctionPassManager &fpm, + const EntityLifter &lifter) { + fpm.addPass(RemoveRemillFunctionReturns(lifter)); } } // namespace anvill diff --git a/libraries/anvill_passes/src/RemoveTrivialPhisAndSelects.cpp b/libraries/anvill_passes/src/RemoveTrivialPhisAndSelects.cpp index acb198ede..b44321892 100644 --- a/libraries/anvill_passes/src/RemoveTrivialPhisAndSelects.cpp +++ b/libraries/anvill_passes/src/RemoveTrivialPhisAndSelects.cpp @@ -30,19 +30,16 @@ namespace anvill { namespace { -class RemoveTrivialPhisAndSelects final : public llvm::FunctionPass { +class RemoveTrivialPhisAndSelects final + : public llvm::PassInfoMixin { public: - RemoveTrivialPhisAndSelects(void) : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &func) final; - - private: - static char ID; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); }; -char RemoveTrivialPhisAndSelects::ID = '\0'; - -bool RemoveTrivialPhisAndSelects::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +RemoveTrivialPhisAndSelects::run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { std::unordered_set remove; std::vector work_list; @@ -116,7 +113,8 @@ bool RemoveTrivialPhisAndSelects::runOnFunction(llvm::Function &func) { } } - return changed; + return changed ? llvm::PreservedAnalyses::none() + : llvm::PreservedAnalyses::all(); } } // namespace @@ -125,8 +123,8 @@ bool RemoveTrivialPhisAndSelects::runOnFunction(llvm::Function &func) { // incoming values or true/false values match. This can happen as a result of // the instruction folding pass that hoists and folds values up through selects // and PHI nodes, followed by the select sinking pass, which pushes values down. -llvm::FunctionPass *CreateRemoveTrivialPhisAndSelects(void) { - return new RemoveTrivialPhisAndSelects; +void AddRemoveTrivialPhisAndSelects(llvm::FunctionPassManager &fpm) { + fpm.addPass(RemoveTrivialPhisAndSelects()); } } // namespace anvill diff --git a/libraries/anvill_passes/src/RemoveUnusedFPClassificationCalls.cpp b/libraries/anvill_passes/src/RemoveUnusedFPClassificationCalls.cpp index dd838bb88..71ec2948a 100644 --- a/libraries/anvill_passes/src/RemoveUnusedFPClassificationCalls.cpp +++ b/libraries/anvill_passes/src/RemoveUnusedFPClassificationCalls.cpp @@ -28,20 +28,17 @@ namespace anvill { namespace { -class RemoveUnusedFPClassificationCalls final : public llvm::FunctionPass { +class RemoveUnusedFPClassificationCalls final + : public llvm::PassInfoMixin { public: - RemoveUnusedFPClassificationCalls(void) : llvm::FunctionPass(ID) {} - - bool runOnFunction(llvm::Function &func) final; - - private: - static char ID; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); }; -char RemoveUnusedFPClassificationCalls::ID = '\0'; - // Try to remove unused floating point classification function calls. -bool RemoveUnusedFPClassificationCalls::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +RemoveUnusedFPClassificationCalls::run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { auto calls = FindFunctionCalls(func, [](llvm::CallBase *call) -> bool { const auto func = call->getCalledFunction(); if (!func) { @@ -61,7 +58,7 @@ bool RemoveUnusedFPClassificationCalls::runOnFunction(llvm::Function &func) { } } - return ret; + return ret ? llvm::PreservedAnalyses::none() : llvm::PreservedAnalyses::all(); } } // namespace @@ -77,8 +74,8 @@ bool RemoveUnusedFPClassificationCalls::runOnFunction(llvm::Function &func) { // NOTE(pag): This pass must be applied before any kind of renaming of lifted // functions is performed, so that we don't accidentally remove // calls to classification functions present in the target binary. -llvm::FunctionPass *CreateRemoveUnusedFPClassificationCalls(void) { - return new RemoveUnusedFPClassificationCalls; +void AddRemoveUnusedFPClassificationCalls(llvm::FunctionPassManager &fpm) { + fpm.addPass(RemoveUnusedFPClassificationCalls()); } } // namespace anvill diff --git a/libraries/anvill_passes/src/SinkSelectionsIntoBranchTargets.cpp b/libraries/anvill_passes/src/SinkSelectionsIntoBranchTargets.cpp index cf74db531..8ec3219ee 100644 --- a/libraries/anvill_passes/src/SinkSelectionsIntoBranchTargets.cpp +++ b/libraries/anvill_passes/src/SinkSelectionsIntoBranchTargets.cpp @@ -44,9 +44,10 @@ using SelectListMap = std::unordered_map; } // namespace -SinkSelectionsIntoBranchTargets *SinkSelectionsIntoBranchTargets::Create( +void SinkSelectionsIntoBranchTargets::Add( + llvm::FunctionPassManager &fpm, ITransformationErrorManager &error_manager) { - return new SinkSelectionsIntoBranchTargets(error_manager); + fpm.addPass(SinkSelectionsIntoBranchTargets(error_manager)); } SinkSelectionsIntoBranchTargets::FunctionAnalysis @@ -153,31 +154,29 @@ void SinkSelectionsIntoBranchTargets::SinkSelectInstructions( } } -bool SinkSelectionsIntoBranchTargets::Run(llvm::Function &function) { +llvm::PreservedAnalyses +SinkSelectionsIntoBranchTargets::Run(llvm::Function &function) { if (function.isDeclaration()) { - return false; + return llvm::PreservedAnalyses::all(); } auto function_analysis = AnalyzeFunction(function); if (function_analysis.replacement_list.empty()) { - return false; + return llvm::PreservedAnalyses::all(); } SinkSelectInstructions(function_analysis); - return true; -} - -llvm::StringRef SinkSelectionsIntoBranchTargets::getPassName(void) const { - return llvm::StringRef("SinkSelectionsIntoBranchTargets"); + return llvm::PreservedAnalyses::none(); } SinkSelectionsIntoBranchTargets::SinkSelectionsIntoBranchTargets( ITransformationErrorManager &error_manager) : BaseFunctionPass(error_manager) {} -llvm::FunctionPass *CreateSinkSelectionsIntoBranchTargets( +void AddSinkSelectionsIntoBranchTargets( + llvm::FunctionPassManager &fpm, ITransformationErrorManager &error_manager) { - return SinkSelectionsIntoBranchTargets::Create(error_manager); + SinkSelectionsIntoBranchTargets::Add(fpm, error_manager); } } // namespace anvill diff --git a/libraries/anvill_passes/src/SinkSelectionsIntoBranchTargets.h b/libraries/anvill_passes/src/SinkSelectionsIntoBranchTargets.h index 4f8b1149b..68958ac78 100644 --- a/libraries/anvill_passes/src/SinkSelectionsIntoBranchTargets.h +++ b/libraries/anvill_passes/src/SinkSelectionsIntoBranchTargets.h @@ -77,18 +77,16 @@ class SinkSelectionsIntoBranchTargets final static void SinkSelectInstructions(const FunctionAnalysis &analysis); // Creates a new SinkSelectionsIntoBranchTargets object - static SinkSelectionsIntoBranchTargets * - Create(ITransformationErrorManager &error_manager); + static void Add(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager); // Function pass entry point - bool Run(llvm::Function &function); + llvm::PreservedAnalyses Run(llvm::Function &function); - // Returns the pass name - virtual llvm::StringRef getPassName(void) const override; + virtual ~SinkSelectionsIntoBranchTargets(void) override = default; private: SinkSelectionsIntoBranchTargets(ITransformationErrorManager &error_manager); - virtual ~SinkSelectionsIntoBranchTargets(void) override = default; }; } // namespace anvill diff --git a/libraries/anvill_passes/src/SplitStackFrameAtReturnAddress.cpp b/libraries/anvill_passes/src/SplitStackFrameAtReturnAddress.cpp index d9fada74c..da557f8f2 100644 --- a/libraries/anvill_passes/src/SplitStackFrameAtReturnAddress.cpp +++ b/libraries/anvill_passes/src/SplitStackFrameAtReturnAddress.cpp @@ -50,14 +50,16 @@ using AllocatedStackFramePartList = std::vector; } // namespace -SplitStackFrameAtReturnAddress *SplitStackFrameAtReturnAddress::Create( +void SplitStackFrameAtReturnAddress::Add( + llvm::FunctionPassManager &fpm, ITransformationErrorManager &error_manager) { - return new SplitStackFrameAtReturnAddress(error_manager); + fpm.addPass(SplitStackFrameAtReturnAddress(error_manager)); } -bool SplitStackFrameAtReturnAddress::Run(llvm::Function &function) { +llvm::PreservedAnalyses +SplitStackFrameAtReturnAddress::Run(llvm::Function &function) { if (function.isDeclaration()) { - return false; + return llvm::PreservedAnalyses::all(); } // Analyze the function first; there may be nothing to do @@ -66,18 +68,18 @@ bool SplitStackFrameAtReturnAddress::Run(llvm::Function &function) { auto error = analysis_res.TakeError(); if (error == StackFrameSplitErrorCode::StackFrameTypeNotFound || error == StackFrameSplitErrorCode::StackFrameAllocaInstNotFound) { - return false; + return llvm::PreservedAnalyses::all(); } EmitError(SeverityType::Error, analysis_res.TakeError(), "The function analysis has failed"); - return false; + return llvm::PreservedAnalyses::all(); } auto analysis = analysis_res.TakeValue(); if (analysis.gep_instr_list.empty()) { - return false; + return llvm::PreservedAnalyses::all(); } // Attempt to split the stack frame @@ -86,7 +88,7 @@ bool SplitStackFrameAtReturnAddress::Run(llvm::Function &function) { EmitError(SeverityType::Fatal, split_res.TakeError(), "The stack frame splitting has failed"); - return true; + return llvm::PreservedAnalyses::none(); } // Do a second analysis, this time it should fail since we deleted @@ -97,7 +99,7 @@ bool SplitStackFrameAtReturnAddress::Run(llvm::Function &function) { SeverityType::Fatal, StackFrameSplitErrorCode::TransformationFailed, "The second function analysis has found unreplaced stack frame usages"); - return true; + return llvm::PreservedAnalyses::none(); } // Make sure that the returned error is the correct one; the type should @@ -110,14 +112,10 @@ bool SplitStackFrameAtReturnAddress::Run(llvm::Function &function) { SeverityType::Fatal, analysis_error, "Failed to verify the correctness of the function transformation"); - return true; + return llvm::PreservedAnalyses::none(); } - return true; -} - -llvm::StringRef SplitStackFrameAtReturnAddress::getPassName(void) const { - return llvm::StringRef("SplitStackFrameAtReturnAddress"); + return llvm::PreservedAnalyses::none(); } Result @@ -545,9 +543,9 @@ SplitStackFrameAtReturnAddress::SplitStackFrameAtReturnAddress( ITransformationErrorManager &error_manager) : BaseFunctionPass(error_manager) {} -llvm::FunctionPass *CreateSplitStackFrameAtReturnAddress( +void AddSplitStackFrameAtReturnAddress(llvm::FunctionPassManager& fpm, ITransformationErrorManager &error_manager) { - return SplitStackFrameAtReturnAddress::Create(error_manager); + SplitStackFrameAtReturnAddress::Add(fpm, error_manager); } } // namespace anvill diff --git a/libraries/anvill_passes/src/SplitStackFrameAtReturnAddress.h b/libraries/anvill_passes/src/SplitStackFrameAtReturnAddress.h index bfc74983f..60ec54482 100644 --- a/libraries/anvill_passes/src/SplitStackFrameAtReturnAddress.h +++ b/libraries/anvill_passes/src/SplitStackFrameAtReturnAddress.h @@ -159,14 +159,11 @@ class SplitStackFrameAtReturnAddress final public: // Creates a new SplitStackFrameAtReturnAddress object - static SplitStackFrameAtReturnAddress * - Create(ITransformationErrorManager &error_manager); + static void Add(llvm::FunctionPassManager &fpm, + ITransformationErrorManager &error_manager); // Function pass entry point - bool Run(llvm::Function &function); - - // Returns the pass name - virtual llvm::StringRef getPassName(void) const override; + llvm::PreservedAnalyses Run(llvm::Function &function); // Analyses the function to determine the necessary steps to split // the function's stack frame @@ -195,9 +192,10 @@ class SplitStackFrameAtReturnAddress final GenerateStackFramePartTypeName(const llvm::Function &function, std::size_t part_number); + virtual ~SplitStackFrameAtReturnAddress(void) override = default; + private: SplitStackFrameAtReturnAddress(ITransformationErrorManager &error_manager); - virtual ~SplitStackFrameAtReturnAddress(void) override = default; }; } // namespace anvill diff --git a/libraries/anvill_passes/src/TransformRemillJumpIntrinsics.cpp b/libraries/anvill_passes/src/TransformRemillJumpIntrinsics.cpp index 1238dd33e..975ba739b 100644 --- a/libraries/anvill_passes/src/TransformRemillJumpIntrinsics.cpp +++ b/libraries/anvill_passes/src/TransformRemillJumpIntrinsics.cpp @@ -25,12 +25,14 @@ #include #include #include -#include #include #include #include #include #include +#include +#include +#include #include #include #include @@ -61,13 +63,14 @@ enum ReturnAddressResult { kUnclassifiableProgramCounter }; -class TransformRemillJumpIntrinsics final : public llvm::FunctionPass { +class TransformRemillJumpIntrinsics final + : public llvm::PassInfoMixin { public: TransformRemillJumpIntrinsics(const EntityLifter &lifter_) - : llvm::FunctionPass(ID), - xref_resolver_(lifter_) {} + : xref_resolver_(lifter_) {} - bool runOnFunction(llvm::Function &func) final; + llvm::PreservedAnalyses run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam); private: ReturnAddressResult QueryReturnAddress(llvm::Module *module, @@ -75,12 +78,9 @@ class TransformRemillJumpIntrinsics final : public llvm::FunctionPass { bool TransformJumpIntrinsic(llvm::CallBase *call); - static char ID; const CrossReferenceResolver xref_resolver_; }; -char TransformRemillJumpIntrinsics::ID = '\0'; - // Returns `true` if `val` is a possible return address ReturnAddressResult TransformRemillJumpIntrinsics::QueryReturnAddress(llvm::Module *module, @@ -176,7 +176,9 @@ bool TransformRemillJumpIntrinsics::TransformJumpIntrinsic( // Try to identify the patterns of `__remill_function_call` that we can // remove. -bool TransformRemillJumpIntrinsics::runOnFunction(llvm::Function &func) { +llvm::PreservedAnalyses +TransformRemillJumpIntrinsics::run(llvm::Function &func, + llvm::FunctionAnalysisManager &fam) { const auto module = func.getParent(); const auto &dl = module->getDataLayout(); auto calls = FindFunctionCalls(func, [&](llvm::CallBase *call) -> bool { @@ -202,17 +204,17 @@ bool TransformRemillJumpIntrinsics::runOnFunction(llvm::Function &func) { // Run private function passes if the jump instrinsics // are replaced - llvm::legacy::FunctionPassManager fpm(module); - fpm.add(llvm::createDeadCodeEliminationPass()); - fpm.add(llvm::createSROAPass()); - fpm.add(llvm::createCFGSimplificationPass()); - fpm.add(llvm::createInstructionCombiningPass()); - fpm.doInitialization(); - fpm.run(func); - fpm.doFinalization(); + llvm::FunctionPassManager fpm; + fpm.addPass(llvm::DCEPass()); + fpm.addPass(llvm::SROA()); + fpm.addPass(llvm::SimplifyCFGPass()); + // TODO(alex): It doesn't seem to like this and complains about the pass not being registered. + // Perhaps it's because we're nesting pass managers? + // fpm.addPass(llvm::InstCombinePass()); + fpm.run(func, fam); } - return ret; + return ret ? llvm::PreservedAnalyses::none() : llvm::PreservedAnalyses::all(); } } // namespace @@ -230,9 +232,9 @@ bool TransformRemillJumpIntrinsics::runOnFunction(llvm::Function &func) { // indirect jump and fixes the intrinsics for them. The pass should be run before // `RemoveRemillFunctionReturns` and as late as possible in the list -llvm::FunctionPass * -CreateTransformRemillJumpIntrinsics(const EntityLifter &lifter) { - return new TransformRemillJumpIntrinsics(lifter); +void AddTransformRemillJumpIntrinsics(llvm::FunctionPassManager &fpm, + const EntityLifter &lifter) { + fpm.addPass(TransformRemillJumpIntrinsics(lifter)); } } // namespace anvill diff --git a/libraries/anvill_passes/tests/src/BrightenPointers.cpp b/libraries/anvill_passes/tests/src/BrightenPointers.cpp index cee1f70b0..facba6d07 100644 --- a/libraries/anvill_passes/tests/src/BrightenPointers.cpp +++ b/libraries/anvill_passes/tests/src/BrightenPointers.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -78,17 +79,19 @@ class BrightenPointersFixture { const std::shared_ptr types; }; */ -bool RunFunctionPass(llvm::Module &module, llvm::FunctionPass *function_pass) { - llvm::legacy::FunctionPassManager pass_manager(&module); - pass_manager.add(function_pass); - - pass_manager.doInitialization(); +bool RunFunctionPass( + llvm::Module &module, + std::function add_function_pass) { + llvm::PassBuilder pass_builder; + llvm::FunctionPassManager fpm; + llvm::FunctionAnalysisManager fam; + pass_builder.registerFunctionAnalyses(fam); + add_function_pass(fpm); for (auto &function : module) { - pass_manager.run(function); + fpm.run(function, fam); } - pass_manager.doFinalization(); return VerifyModule(&module); } @@ -99,7 +102,9 @@ TEST_SUITE("BrightenPointers") { llvm::LLVMContext context; auto mod = LoadTestData(context, "gep_add.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } @@ -107,7 +112,9 @@ TEST_SUITE("BrightenPointers") { llvm::LLVMContext context; auto mod = LoadTestData(context, "multiple_bitcast.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } @@ -115,7 +122,9 @@ TEST_SUITE("BrightenPointers") { llvm::LLVMContext context; auto mod = LoadTestData(context, "loop_test.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } @@ -123,7 +132,9 @@ TEST_SUITE("BrightenPointers") { llvm::LLVMContext context; auto mod = LoadTestData(context, "rx_message.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); // mod->print(llvm::errs(), nullptr); @@ -135,7 +146,9 @@ TEST_SUITE("BrightenPointers") { llvm::LLVMContext context; auto mod = LoadTestData(context, "chall2.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); // mod->print(llvm::errs(), nullptr); @@ -146,28 +159,36 @@ TEST_SUITE("BrightenPointers") { llvm::LLVMContext context; auto mod = LoadTestData(context, "ret0.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("jmp0") { llvm::LLVMContext context; auto mod = LoadTestData(context, "jmp0.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_array_swap") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_array_swap_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_binja_var_none_type") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_binja_var_none_type_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); mod->print(llvm::errs(), nullptr); CHECK(checkMod(*mod)); } @@ -175,91 +196,117 @@ TEST_SUITE("BrightenPointers") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_bitops_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_binops") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_binops_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_cast") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_cast_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_init_list_rt.ll") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_init_list_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_inttoptr_rt.ll") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_inttoptr_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_nullptr_rt.ll") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_nullptr_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_ret0_rt.ll") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_ret0_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_struct_rt.ll") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_struct_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_struct_swap_rt.ll") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_struct_swap_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_trunc_rt.ll") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_trunc_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_zeroinit.ll") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_zeroinit_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_zext_rt.ll") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_zext_rt.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } TEST_CASE("test_rx.ll") { llvm::LLVMContext context; auto mod = LoadTestData(context, "test_rx.ll"); REQUIRE(mod != nullptr); - CHECK(RunFunctionPass(*mod, CreateBrightenPointerOperations(250U))); + CHECK(RunFunctionPass(*mod, [](llvm::FunctionPassManager &fpm) { + AddBrightenPointerOperations(fpm, 250U); + })); CHECK(checkMod(*mod)); } } diff --git a/libraries/anvill_passes/tests/src/InstructionFolderPass.cpp b/libraries/anvill_passes/tests/src/InstructionFolderPass.cpp index 8276587c4..4a175e464 100644 --- a/libraries/anvill_passes/tests/src/InstructionFolderPass.cpp +++ b/libraries/anvill_passes/tests/src/InstructionFolderPass.cpp @@ -44,7 +44,9 @@ TEST_SUITE("InstructionFolderPass") { auto error_manager = ITransformationErrorManager::Create(); CHECK(RunFunctionPass(module.get(), - CreateInstructionFolderPass(*error_manager.get()))); + [&error_manager](llvm::FunctionPassManager &fpm) { + AddInstructionFolderPass(fpm, *error_manager.get()); + })); for (const auto &error : error_manager->ErrorList()) { CHECK_MESSAGE(false, error.description); diff --git a/libraries/anvill_passes/tests/src/RecoverStackFrameInformation.cpp b/libraries/anvill_passes/tests/src/RecoverStackFrameInformation.cpp index 71e18ccb1..a488243b3 100644 --- a/libraries/anvill_passes/tests/src/RecoverStackFrameInformation.cpp +++ b/libraries/anvill_passes/tests/src/RecoverStackFrameInformation.cpp @@ -74,9 +74,12 @@ TEST_SUITE("RecoverStackFrameInformation") { lift_options.stack_frame_lower_padding = lift_options.stack_frame_higher_padding = padding_bytes / 2U; - CHECK(RunFunctionPass(module.get(), - CreateRecoverStackFrameInformation( - *error_manager.get(), lift_options))); + CHECK(RunFunctionPass( + module.get(), + [&error_manager, &lift_options](llvm::FunctionPassManager &fpm) { + AddRecoverStackFrameInformation(fpm, *error_manager.get(), + lift_options); + })); for (const auto &error : error_manager->ErrorList()) { diff --git a/libraries/anvill_passes/tests/src/SinkSelectionsIntoBranchTargets.cpp b/libraries/anvill_passes/tests/src/SinkSelectionsIntoBranchTargets.cpp index 9bbb01cea..bd69a2cc5 100644 --- a/libraries/anvill_passes/tests/src/SinkSelectionsIntoBranchTargets.cpp +++ b/libraries/anvill_passes/tests/src/SinkSelectionsIntoBranchTargets.cpp @@ -34,8 +34,10 @@ TEST_SUITE("SinkSelectionsIntoBranchTargets") { REQUIRE(module != nullptr); auto error_manager = ITransformationErrorManager::Create(); - CHECK(RunFunctionPass(module.get(), CreateSinkSelectionsIntoBranchTargets( - *error_manager.get()))); + CHECK(RunFunctionPass( + module.get(), [&error_manager](llvm::FunctionPassManager &fpm) { + AddSinkSelectionsIntoBranchTargets(fpm, *error_manager.get()); + })); for (const auto &error : error_manager->ErrorList()) { CHECK_MESSAGE(false, error.description); diff --git a/libraries/anvill_passes/tests/src/SplitStackFrameAtReturnAddress.cpp b/libraries/anvill_passes/tests/src/SplitStackFrameAtReturnAddress.cpp index cfeb36e39..5d0bf1155 100644 --- a/libraries/anvill_passes/tests/src/SplitStackFrameAtReturnAddress.cpp +++ b/libraries/anvill_passes/tests/src/SplitStackFrameAtReturnAddress.cpp @@ -34,8 +34,10 @@ TEST_SUITE("SplitStackFrameAtReturnAddress") { REQUIRE(module != nullptr); auto error_manager = ITransformationErrorManager::Create(); - CHECK(RunFunctionPass(module.get(), CreateSplitStackFrameAtReturnAddress( - *error_manager.get()))); + CHECK(RunFunctionPass( + module.get(), [&error_manager](llvm::FunctionPassManager &fpm) { + AddSplitStackFrameAtReturnAddress(fpm, *error_manager.get()); + })); for (const auto &error : error_manager->ErrorList()) { CHECK_MESSAGE(false, error.description); diff --git a/libraries/anvill_passes/tests/src/TransformRemillJump.cpp b/libraries/anvill_passes/tests/src/TransformRemillJump.cpp index aaa2be47e..3a7466666 100644 --- a/libraries/anvill_passes/tests/src/TransformRemillJump.cpp +++ b/libraries/anvill_passes/tests/src/TransformRemillJump.cpp @@ -44,7 +44,9 @@ TEST_SUITE("TransformRemillJump_Test0") { anvill::EntityLifter lifter(options, nullptr, nullptr); CHECK(RunFunctionPass(module.get(), - CreateTransformRemillJumpIntrinsics(lifter))); + [&lifter](llvm::FunctionPassManager &fpm) { + AddTransformRemillJumpIntrinsics(fpm, lifter); + })); const auto ret_func = module->getFunction("__remill_function_return"); const auto jmp_func = module->getFunction("__remill_jump"); @@ -69,7 +71,9 @@ TEST_SUITE("TransformRemillJump_Test1") { anvill::EntityLifter lifter(options, nullptr, nullptr); CHECK(RunFunctionPass(module.get(), - CreateTransformRemillJumpIntrinsics(lifter))); + [&lifter](llvm::FunctionPassManager &fpm) { + AddTransformRemillJumpIntrinsics(fpm, lifter); + })); const auto ret_func = module->getFunction("__remill_function_return"); const auto jmp_func = module->getFunction("__remill_jump"); @@ -96,7 +100,9 @@ TEST_SUITE("TransformRemillJump_ARM32_0") { anvill::EntityLifter lifter(options, nullptr, nullptr); CHECK(RunFunctionPass(module.get(), - CreateTransformRemillJumpIntrinsics(lifter))); + [&lifter](llvm::FunctionPassManager &fpm) { + AddTransformRemillJumpIntrinsics(fpm, lifter); + })); const auto ret_func = module->getFunction("__remill_function_return"); const auto jmp_func = module->getFunction("__remill_jump"); @@ -123,7 +129,9 @@ TEST_SUITE("TransformRemillJump_ARM32_1") { anvill::EntityLifter lifter(options, nullptr, nullptr); CHECK(RunFunctionPass(module.get(), - CreateTransformRemillJumpIntrinsics(lifter))); + [&lifter](llvm::FunctionPassManager &fpm) { + AddTransformRemillJumpIntrinsics(fpm, lifter); + })); const auto ret_func = module->getFunction("__remill_function_return"); const auto jmp_func = module->getFunction("__remill_jump"); diff --git a/libraries/anvill_passes/tests/src/Utils.cpp b/libraries/anvill_passes/tests/src/Utils.cpp index 20f60cade..28473ea96 100644 --- a/libraries/anvill_passes/tests/src/Utils.cpp +++ b/libraries/anvill_passes/tests/src/Utils.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -81,17 +82,19 @@ std::unique_ptr LoadTestData(llvm::LLVMContext &context, return llvm_module; } -bool RunFunctionPass(llvm::Module *module, llvm::FunctionPass *function_pass) { - llvm::legacy::FunctionPassManager pass_manager(module); - pass_manager.add(function_pass); - - pass_manager.doInitialization(); +bool RunFunctionPass( + llvm::Module *module, + std::function add_function_pass) { + llvm::PassBuilder pass_builder; + llvm::FunctionPassManager fpm; + llvm::FunctionAnalysisManager fam; + pass_builder.registerFunctionAnalyses(fam); + add_function_pass(fpm); for (auto &function : *module) { - pass_manager.run(function); + fpm.run(function, fam); } - pass_manager.doFinalization(); return VerifyModule(module); } diff --git a/libraries/anvill_passes/tests/src/Utils.h b/libraries/anvill_passes/tests/src/Utils.h index d9a554258..054e0b4c0 100644 --- a/libraries/anvill_passes/tests/src/Utils.h +++ b/libraries/anvill_passes/tests/src/Utils.h @@ -17,8 +17,8 @@ #pragma once -#include #include +#include namespace anvill { @@ -27,7 +27,9 @@ bool VerifyModule(llvm::Module *module); std::unique_ptr LoadTestData(llvm::LLVMContext &context, const std::string &data_name); -bool RunFunctionPass(llvm::Module *module, llvm::FunctionPass *function_pass); +bool RunFunctionPass( + llvm::Module *module, + std::function function_pass); struct Platform final { std::string os; diff --git a/libraries/anvill_passes/tests/src/XorConversionPass.cpp b/libraries/anvill_passes/tests/src/XorConversionPass.cpp index 0a07c5dea..767fdeabe 100644 --- a/libraries/anvill_passes/tests/src/XorConversionPass.cpp +++ b/libraries/anvill_passes/tests/src/XorConversionPass.cpp @@ -45,7 +45,9 @@ TEST_SUITE("XorConversion") { // memory and types will not get used and create lifter with null anvill::EntityLifter lifter(options, nullptr, nullptr); - CHECK(RunFunctionPass(module.get(), CreateConvertXorToCmp())); + CHECK(RunFunctionPass(module.get(), [](llvm::FunctionPassManager &fpm) { + AddConvertXorToCmp(fpm); + })); const auto xor_as_not = module->getFunction("xor_as_not"); int xor_count = 0; @@ -76,7 +78,9 @@ TEST_SUITE("XorConversion") { // memory and types will not get used and create lifter with null anvill::EntityLifter lifter(options, nullptr, nullptr); - CHECK(RunFunctionPass(module.get(), CreateConvertXorToCmp())); + CHECK(RunFunctionPass(module.get(), [](llvm::FunctionPassManager &fpm) { + AddConvertXorToCmp(fpm); + })); const auto xor_as_not_nochange = module->getFunction("xor_as_not_nochange"); int xor_count = 0;