mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
87611643ad
Before this commit, we assigned names to struct types without looking at the function names of which they were return types. Now we do, so that the name of the generated type for the function `f` is `f_ret_type`. This also fixes errors when reparsing the generated C code, where the names of the struct types did not match.
98 lines
3.2 KiB
C++
98 lines
3.2 KiB
C++
// LLVM includes
|
|
#include <llvm/IR/Module.h>
|
|
|
|
// revng includes
|
|
#include <revng/Support/Assert.h>
|
|
|
|
// local includes
|
|
#include "DecompilationHelpers.h"
|
|
#include "IRASTTypeTranslation.h"
|
|
#include "TypeDeclCreationAction.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace clang {
|
|
namespace tooling {
|
|
|
|
using TypeDeclMap = TypeDeclCreationAction::TypeDeclMap;
|
|
using FieldDeclMap = TypeDeclCreationAction::FieldDeclMap;
|
|
using TypePair = std::pair<const llvm::Type *const, clang::TypeDecl *>;
|
|
|
|
static std::vector<TypePair> createTypeDecls(ASTContext &Context,
|
|
TranslationUnitDecl *TUDecl,
|
|
TypeDeclMap &TypeDecls,
|
|
FieldDeclMap &FieldDecls,
|
|
Function *F) {
|
|
std::vector<TypePair> Result;
|
|
const llvm::FunctionType *FType = F->getFunctionType();
|
|
|
|
if (llvm::Type *RetTy = dyn_cast<llvm::StructType>(FType->getReturnType())) {
|
|
|
|
IRASTTypeTranslation::getOrCreateQualType(RetTy,
|
|
F,
|
|
Context,
|
|
*TUDecl,
|
|
TypeDecls,
|
|
FieldDecls);
|
|
|
|
revng_assert(TypeDecls.count(RetTy));
|
|
Result.push_back(*TypeDecls.find(RetTy));
|
|
}
|
|
|
|
for (const llvm::Type *T : FType->params()) {
|
|
// For now we don't handle function prototypes with struct arguments
|
|
revng_assert(not isa<llvm::StructType>(T));
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
class TypeDeclCreator : public ASTConsumer {
|
|
public:
|
|
explicit TypeDeclCreator(llvm::Function &F,
|
|
TypeDeclMap &TDecls,
|
|
FieldDeclMap &FieldDecls) :
|
|
TheF(F), TypeDecls(TDecls), FieldDecls(FieldDecls) {}
|
|
|
|
virtual void HandleTranslationUnit(ASTContext &C) override;
|
|
|
|
private:
|
|
llvm::Function &TheF;
|
|
TypeDeclMap &TypeDecls;
|
|
FieldDeclMap &FieldDecls;
|
|
};
|
|
|
|
void TypeDeclCreator::HandleTranslationUnit(ASTContext &C) {
|
|
llvm::Module &M = *TheF.getParent();
|
|
TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
|
|
|
|
std::set<Function *> Called = getDirectlyCalledFunctions(TheF);
|
|
// we need TheF to properly declare its return type if needed
|
|
Called.insert(&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());
|
|
std::vector<TypePair> NewTypeDecls = createTypeDecls(C,
|
|
TUDecl,
|
|
TypeDecls,
|
|
FieldDecls,
|
|
F);
|
|
for (TypePair &TD : NewTypeDecls)
|
|
TypeDecls.insert(TD);
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<ASTConsumer> TypeDeclCreationAction::newASTConsumer() {
|
|
return std::make_unique<TypeDeclCreator>(F, TypeDecls, FieldDecls);
|
|
}
|
|
|
|
std::unique_ptr<ASTConsumer>
|
|
TypeDeclCreationAction::CreateASTConsumer(CompilerInstance &, llvm::StringRef) {
|
|
return newASTConsumer();
|
|
}
|
|
|
|
} // end namespace tooling
|
|
} // end namespace clang
|