Files
revng-revng/lib/BasicAnalyses/GeneratedCodeBasicInfo.cpp
T
Pietro Fezzardi 7ff24ac761 GCBI: remove assertion on Dispatcher != nullptr
This assertion was executed in the `runOnModule` method of the GCBI
pass, but it is too strict.

Asserting that Dispatcher != nullptr during the execution of the pass
prevents the pass from successfully running on a Module without a
Dispatcher.
This is unfortunate, because some passes that depend on GCBI in revng-c
actually do that. They do so because they are not really interested in
the Dispatcher at all. They only use GCBI to access information on the
Stack Pointer.

In fact, the check for Dispatcher being != from nullptr is already
performed also in the `dispatcher()` method which is the sane thing to
do. This commit removes the assertion from the `runOnModule` method and
leaves it in the `dispatcher` method.
This allows to run the pass successfully even on a Module without the
Dispatcher, while not changing the contract of this pass (i.e. that when
you call the `dispatcher` method you get a nonnull pointer).
2020-12-29 14:51:38 +01:00

144 lines
4.5 KiB
C++

/// \file GeneratedCodeBasicInfo.cpp
/// \brief Implements the GeneratedCodeBasicInfo pass which provides basic
/// information about the translated code (e.g., which CSV is the PC).
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <queue>
#include <set>
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "revng/BasicAnalyses/GeneratedCodeBasicInfo.h"
#include "revng/Support/Debug.h"
using namespace llvm;
char GeneratedCodeBasicInfo::ID = 0;
using RegisterGCBI = RegisterPass<GeneratedCodeBasicInfo>;
static RegisterGCBI X("gcbi", "Generated Code Basic Info", true, true);
bool GeneratedCodeBasicInfo::runOnModule(Module &M) {
Function &F = *M.getFunction("root");
NewPC = M.getFunction("newpc");
if (NewPC != nullptr) {
MetaAddressStruct = cast<StructType>(NewPC->arg_begin()->getType());
}
revng_log(PassesLog, "Starting GeneratedCodeBasicInfo");
RootFunction = &F;
const char *MDName = "revng.input.architecture";
NamedMDNode *InputArchMD = M.getOrInsertNamedMetadata(MDName);
auto *Tuple = dyn_cast<MDTuple>(InputArchMD->getOperand(0));
QuickMetadata QMD(M.getContext());
{
unsigned Index = 0;
StringRef ArchTypeName = QMD.extract<StringRef>(Tuple, Index++);
ArchType = Triple::getArchTypeForLLVMName(ArchTypeName);
InstructionAlignment = QMD.extract<uint32_t>(Tuple, Index++);
DelaySlotSize = QMD.extract<uint32_t>(Tuple, Index++);
PC = M.getGlobalVariable(QMD.extract<StringRef>(Tuple, Index++), true);
SP = M.getGlobalVariable(QMD.extract<StringRef>(Tuple, Index++), true);
auto Operands = QMD.extract<MDTuple *>(Tuple, Index++)->operands();
for (const MDOperand &Operand : Operands) {
StringRef Name = QMD.extract<StringRef>(Operand.get());
revng_assert(Name != "pc", "PC should not be considered an ABI register");
GlobalVariable *CSV = M.getGlobalVariable(Name, true);
ABIRegisters.push_back(CSV);
ABIRegistersSet.insert(CSV);
}
}
Type *PCType = PC->getType()->getPointerElementType();
PCRegSize = M.getDataLayout().getTypeAllocSize(PCType);
for (BasicBlock &BB : F) {
if (!BB.empty()) {
switch (getType(&BB)) {
case BlockType::RootDispatcherBlock:
revng_assert(Dispatcher == nullptr);
Dispatcher = &BB;
break;
case BlockType::DispatcherFailureBlock:
revng_assert(DispatcherFail == nullptr);
DispatcherFail = &BB;
break;
case BlockType::AnyPCBlock:
revng_assert(AnyPC == nullptr);
AnyPC = &BB;
break;
case BlockType::UnexpectedPCBlock:
revng_assert(UnexpectedPC == nullptr);
UnexpectedPC = &BB;
break;
case BlockType::JumpTargetBlock: {
auto *Call = cast<CallInst>(&*BB.begin());
revng_assert(Call->getCalledFunction()->getName() == "newpc");
JumpTargets[MetaAddress::fromConstant(Call->getArgOperand(0))] = &BB;
break;
}
case BlockType::RootDispatcherHelperBlock:
case BlockType::IndirectBranchDispatcherHelperBlock:
case BlockType::EntryPoint:
case BlockType::ExternalJumpsHandlerBlock:
case BlockType::TranslatedBlock:
// Nothing to do here
break;
}
}
}
if (auto *NamedMD = M.getNamedMetadata("revng.csv")) {
auto *Tuple = cast<MDTuple>(NamedMD->getOperand(0));
for (const MDOperand &Operand : Tuple->operands()) {
auto *CSV = cast<GlobalVariable>(QMD.extract<Constant *>(Operand.get()));
CSVs.push_back(CSV);
}
}
revng_log(PassesLog, "Ending GeneratedCodeBasicInfo");
return false;
}
GeneratedCodeBasicInfo::Successors
GeneratedCodeBasicInfo::getSuccessors(BasicBlock *BB) const {
Successors Result;
df_iterator_default_set<BasicBlock *> Visited;
Visited.insert(AnyPC);
Visited.insert(UnexpectedPC);
for (BasicBlock *Block : depth_first_ext(BB, Visited)) {
for (BasicBlock *Successor : successors(Block)) {
MetaAddress Address = getBasicBlockPC(Successor);
const auto IBDHB = BlockType::IndirectBranchDispatcherHelperBlock;
if (Address.isValid()) {
Visited.insert(Successor);
Result.Addresses.insert(Address);
} else if (Successor == AnyPC) {
Result.AnyPC = true;
} else if (Successor == UnexpectedPC) {
Result.UnexpectedPC = true;
} else if (getType(Successor) == IBDHB) {
// Ignore
} else {
Result.Other = true;
}
}
}
return Result;
}