mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
d91ca93b5b
Before this commit, `MakeEnvNullPass` was substituting uses of `env` with uses of `nullptr`. This operation was introducing undefined behavior, and subsequent optimizations were allowed to mark BasicBlocks where it occured as unreachable, eventually leading to their wrong removal. This commit fixes the substitution, properly replacing loads from `env` with `nullptr`. This should never cause undefined behavior anymore, because the results from load from `env` is never referenced in isolated functions.
72 lines
2.0 KiB
C++
72 lines
2.0 KiB
C++
//
|
|
// Copyright (c) rev.ng Srls. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "revng/Support/IRHelpers.h"
|
|
|
|
#include "revng-c/MakeEnvNull/MakeEnvNull.h"
|
|
|
|
bool MakeEnvNullPass::runOnFunction(llvm::Function &F) {
|
|
|
|
bool Changed = false;
|
|
|
|
if (not F.getMetadata("revng.func.entry"))
|
|
return Changed;
|
|
|
|
llvm::Module *M = F.getParent();
|
|
llvm::GlobalVariable *Env = M->getGlobalVariable("env",
|
|
/* AllowInternal */ true);
|
|
|
|
llvm::SmallPtrSet<llvm::LoadInst *, 8> LoadsFromEnvInF;
|
|
for (llvm::Use &EnvUse : Env->uses()) {
|
|
|
|
if (auto *I = llvm::dyn_cast<llvm::Instruction>(EnvUse.getUser())) {
|
|
|
|
if (I->getFunction() != &F)
|
|
continue;
|
|
|
|
// At this point, all uses of env in a function should be loads
|
|
LoadsFromEnvInF.insert(llvm::cast<llvm::LoadInst>(I));
|
|
|
|
} else if (auto *CE = dyn_cast<llvm::ConstantExpr>(EnvUse.getUser())) {
|
|
|
|
if (not CE->isCast())
|
|
continue;
|
|
|
|
for (llvm::Use &CEUse : CE->uses()) {
|
|
if (auto *I = llvm::dyn_cast<llvm::Instruction>(CEUse.getUser())) {
|
|
|
|
if (I->getFunction() != &F)
|
|
continue;
|
|
|
|
// At this point, all uses of env in a function should be loads
|
|
LoadsFromEnvInF.insert(llvm::cast<llvm::LoadInst>(I));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (llvm::LoadInst *L : LoadsFromEnvInF) {
|
|
llvm::Type *LoadType = L->getType();
|
|
auto *Null = llvm::Constant::getNullValue(LoadType);
|
|
L->replaceAllUsesWith(Null);
|
|
}
|
|
|
|
Changed = not LoadsFromEnvInF.empty();
|
|
return Changed;
|
|
}
|
|
|
|
char MakeEnvNullPass::ID = 0;
|
|
|
|
using llvm::RegisterPass;
|
|
using Pass = MakeEnvNullPass;
|
|
static RegisterPass<Pass> RegisterMakeEnvNull("make-env-null",
|
|
"Pass that substitutes env with "
|
|
"a null pointer");
|