Files
revng-revng/lib/MakeEnvNull/MakeEnvNull.cpp
T
Pietro Fezzardi d91ca93b5b MakeEnvNull: fix env substitution
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.
2021-01-22 17:23:55 +01:00

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");