Files
revng-revng/lib/Decompiler/FuncDeclCreationAction.cpp
T
2019-04-02 11:57:07 +02:00

164 lines
6.3 KiB
C++

// LLVM includes
#include <llvm/ADT/SmallVector.h>
#include <llvm/IR/Module.h>
// revng includes
#include <revng/Support/Assert.h>
// local includes
#include "DecompilationHelpers.h"
#include "FuncDeclCreationAction.h"
#include "IRASTTypeTranslation.h"
#include "Mangling.h"
using namespace llvm;
namespace clang {
namespace tooling {
using FunctionsMap = FuncDeclCreationAction::FunctionsMap;
using TypeDeclMap = std::map<const llvm::Type *, clang::TypeDecl *>;
using FieldDeclMap = std::map<clang::TypeDecl *,
llvm::SmallVector<clang::FieldDecl *, 8>>;
static FunctionDecl *createFunDecl(ASTContext &Context,
TranslationUnitDecl *TUDecl,
TypeDeclMap &TypeDecls,
FieldDeclMap &FieldDecls,
Function *F,
bool hasBody) {
const llvm::FunctionType *FType = F->getFunctionType();
llvm::Type *RetTy = FType->getReturnType();
QualType RetType = IRASTTypeTranslation::getOrCreateQualType(RetTy,
Context,
*TUDecl,
TypeDecls,
FieldDecls);
SmallVector<QualType, 4> VoidArgsTy(1, Context.VoidTy);
SmallVector<QualType, 4> ArgTypes = {};
for (const llvm::Type *T : FType->params()) {
// In function declarations all pointers parameters are void *.
// This is a temporary workaround to reduce warnings
QualType ArgType = Context.VoidPtrTy;
if (not isa<llvm::PointerType>(T))
ArgType = IRASTTypeTranslation::getOrCreateQualType(T,
Context,
*TUDecl,
TypeDecls,
FieldDecls);
ArgTypes.push_back(ArgType);
}
const bool HasNoParams = ArgTypes.empty();
if (HasNoParams)
ArgTypes.push_back(Context.VoidTy);
using ExtProtoInfo = FunctionProtoType::ExtProtoInfo;
QualType FDeclType = Context.getFunctionType(RetType,
ArgTypes,
ExtProtoInfo());
const llvm::StringRef FName = F->getName();
revng_assert(not FName.empty());
IdentifierInfo &FunId = Context.Idents.get(makeCIdentifier(FName));
StorageClass FunStorage = hasBody ? StorageClass::SC_Static :
StorageClass::SC_Extern;
FunctionDecl *NewFDecl = FunctionDecl::Create(Context,
TUDecl,
{},
{},
&FunId,
FDeclType,
nullptr,
FunStorage);
TUDecl->addDecl(NewFDecl);
int N = 0;
auto ParmDecls = SmallVector<ParmVarDecl *, 4>(ArgTypes.size(), nullptr);
for (QualType ArgTy : ArgTypes) {
int ParamIdx = N++;
IdentifierInfo *ParmId = nullptr;
if (not HasNoParams)
ParmId = &Context.Idents.get("param_" + std::to_string(ParamIdx));
ParmVarDecl *P = ParmVarDecl::Create(Context,
NewFDecl,
{},
{},
ParmId,
ArgTy,
nullptr,
StorageClass::SC_None,
nullptr);
P->setScopeInfo(0, ParamIdx);
ParmDecls[ParamIdx] = P;
}
NewFDecl->setParams(ParmDecls);
return NewFDecl;
}
class FuncDeclCreator : public ASTConsumer {
public:
explicit FuncDeclCreator(llvm::Function &F,
FunctionsMap &FDecls,
TypeDeclMap &TDecls,
FieldDeclMap &FieldDecls) :
TheF(F),
FunctionDecls(FDecls),
TypeDecls(TDecls),
FieldDecls(FieldDecls) {}
virtual void HandleTranslationUnit(ASTContext &Context) override {
llvm::Module &M = *TheF.getParent();
TranslationUnitDecl *TUDecl = Context.getTranslationUnitDecl();
std::set<Function *> Called = getDirectlyCalledFunctions(TheF);
Called.erase(&TheF);
// we need abort for decompiling UnreachableInst
Called.insert(M.getFunction("abort"));
for (Function *F : Called) {
const llvm::StringRef FName = F->getName();
revng_assert(not FName.empty());
FunctionDecl *NewFDecl = createFunDecl(Context,
TUDecl,
TypeDecls,
FieldDecls,
F,
false);
FunctionDecls[F] = NewFDecl;
}
const llvm::StringRef FName = TheF.getName();
revng_assert(not FName.empty());
revng_assert(FName.startswith("bb."));
// This is actually a definition, because the isolated function need will
// be fully decompiled and it needs a body.
// This definition starts as a declaration that is than inflated by the
// ASTBuildAnalysis.
FunctionDecl *NewFDecl = createFunDecl(Context,
TUDecl,
TypeDecls,
FieldDecls,
&TheF,
true);
FunctionDecls[&TheF] = NewFDecl;
}
private:
llvm::Function &TheF;
FunctionsMap &FunctionDecls;
TypeDeclMap &TypeDecls;
FieldDeclMap &FieldDecls;
};
std::unique_ptr<ASTConsumer> FuncDeclCreationAction::newASTConsumer() {
return std::make_unique<FuncDeclCreator>(F,
FunctionDecls,
TypeDecls,
FieldDecls);
}
} // end namespace tooling
} // end namespace clang