diff --git a/lib/Decompiler/CMakeLists.txt b/lib/Decompiler/CMakeLists.txt index 01946da86..9508c403f 100644 --- a/lib/Decompiler/CMakeLists.txt +++ b/lib/Decompiler/CMakeLists.txt @@ -4,6 +4,7 @@ revng_add_analyses_library(Decompiler revngc ASTBuildAnalysis.cpp + DLACreateInterProceduralTypes.cpp DLAHelpers.cpp DLAPass.cpp DLAStep.cpp diff --git a/lib/Decompiler/DLACreateInterProceduralTypes.cpp b/lib/Decompiler/DLACreateInterProceduralTypes.cpp new file mode 100644 index 000000000..e67cc530a --- /dev/null +++ b/lib/Decompiler/DLACreateInterProceduralTypes.cpp @@ -0,0 +1,104 @@ +// +// Copyright (c) rev.ng Srls. See LICENSE.md for details. +// + +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" + +#include "revng/Support/IRHelpers.h" + +#include "DLAStep.h" +#include "DLATypeSystem.h" + +using namespace dla; +using namespace llvm; + +using StepT = CreateInterproceduralTypes; + +bool StepT::runOnTypeSystem(LayoutTypeSystem &TS) { + const Module &M = TS.getModule(); + for (const Function &F : M.functions()) { + if (F.isIntrinsic() or not F.getMetadata("revng.func.entry")) + continue; + revng_assert(not F.isVarArg()); + + // Create the Function's return types + auto FRetTypes = TS.getOrCreateLayoutTypes(F); + + // Create types for the Function's arguments + for (const Argument &Arg : F.args()) { + // Arguments can only be integers and pointers + revng_assert(isa(Arg.getType()) + or isa(Arg.getType())); + auto N = TS.getOrCreateLayoutTypes(Arg).size(); + // Given that arguments can only be integers or pointers, we should only + // create a single LayoutType for each argument + revng_assert(N == 1ULL); + } + + for (const BasicBlock &B : F) { + for (const Instruction &I : B) { + if (auto *Call = dyn_cast(&I)) { + const Function *Callee = getCallee(Call); + if (Callee->isIntrinsic() + or not Callee->getMetadata("revng.func.entry")) { + continue; + } + unsigned ArgNo = 0U; + for (const Argument &FormalArg : Callee->args()) { + Value *ActualArg = Call->getOperand(ArgNo); + revng_assert(isa(ActualArg->getType()) + or isa(ActualArg->getType())); + revng_assert(isa(FormalArg.getType()) + or isa(FormalArg.getType())); + auto ActualTypes = TS.getOrCreateLayoutTypes(*ActualArg); + auto FormalTypes = TS.getOrCreateLayoutTypes(FormalArg); + revng_assert(1ULL == ActualTypes.size() == FormalTypes.size()); + auto FieldNum = FormalTypes.size(); + for (auto FieldId = 0ULL; FieldId < FieldNum; ++FieldId) { + // Actual type inherits from formal type + TS.addInheritanceLink(ActualTypes[FieldId].first, + FormalTypes[FieldId].first); + } + ++ArgNo; + } + } else if (auto *PHI = dyn_cast(&I)) { + revng_assert(isa(PHI->getType()) + or isa(PHI->getType())); + auto PHITypes = TS.getOrCreateLayoutTypes(*PHI); + for (const Use &Incoming : PHI->incoming_values()) { + revng_assert(isa(Incoming->getType()) + or isa(Incoming->getType())); + auto InTypes = TS.getOrCreateLayoutTypes(*Incoming.get()); + revng_assert(1ULL == PHITypes.size() == InTypes.size()); + auto FieldNum = PHITypes.size(); + for (auto FieldId = 0ULL; FieldId < FieldNum; ++FieldId) { + // Incoming type inherits from PHI type + TS.addInheritanceLink(InTypes[FieldId].first, + PHITypes[FieldId].first); + } + } + } else if (auto *RetI = dyn_cast(&I)) { + if (Value *RetVal = RetI->getReturnValue()) { + revng_assert(isa(RetVal->getType()) + or isa(RetVal->getType()) + or isa(RetVal->getType())); + auto RetTypes = TS.getOrCreateLayoutTypes(*RetVal); + revng_assert(RetTypes.size() == FRetTypes.size()); + auto FieldNum = RetTypes.size(); + for (auto FieldId = 0ULL; FieldId < FieldNum; ++FieldId) { + // Return Operand type inherits from Function return type + if (RetTypes[FieldId].first != nullptr) + TS.addInheritanceLink(RetTypes[FieldId].first, + FRetTypes[FieldId].first); + } + } + } + } + } + } + revng_assert(TS.verifyConsistency()); + return TS.getNumLayouts() != 0; +} diff --git a/lib/Decompiler/DLAPass.cpp b/lib/Decompiler/DLAPass.cpp index 281768f6d..f5188ed97 100644 --- a/lib/Decompiler/DLAPass.cpp +++ b/lib/Decompiler/DLAPass.cpp @@ -4,7 +4,6 @@ #include "revng-c/Decompiler/DLAPass.h" -// Local includes #include "DLAStep.h" #include "DLATypeSystem.h" diff --git a/lib/Decompiler/DLAStep.h b/lib/Decompiler/DLAStep.h index 53a39f6b8..822bf9153 100644 --- a/lib/Decompiler/DLAStep.h +++ b/lib/Decompiler/DLAStep.h @@ -64,7 +64,7 @@ public: virtual ~CreateInterproceduralTypes() override = default; - virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override { return true; } + virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override; }; /// dla::Step that creates types for LLVM Values inside Functions and edges